使用 webpack 为 react-lottie 从主包中排除 JSON 文件
Posted
技术标签:
【中文标题】使用 webpack 为 react-lottie 从主包中排除 JSON 文件【英文标题】:Exclude JSON files from the main bundle with webpack for react-lottie 【发布时间】:2019-04-06 05:47:06 【问题描述】:在我们的 Web 应用程序中,我们有一些 JSON 文件,每个文件大约 10-80k 行。这些都包含在我们的主包中。这些由名为 react-lottie 的动画插件使用。
我们webpack.config.js
的一个例子
module.exports =
entry: ["./src/index.js"],
module:
rules: [
test: /\.(js|jsx)$/, exclude: /node_modules/, use: ["babel-loader"] ,
test: /\.(jpg|png|gif|ico)$/,
use:
loader: "file-loader",
options: name: "[path][name].[hash].[ext]"
]
,
resolve: extensions: ["*", ".js", ".jsx"] ,
output:
path: __dirname + "/dist",
publicPath: "/",
filename: "[name].[hash].js"
,
plugins: [
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin( hash: false, template: "src/index.html" ),
new DashboardPlugin(),
new CopyWebpackPlugin([
from: "src/components/Assets/BookingBar.js",
to: "assets/BookingBar.js"
]),
new BundleAnalyzerPlugin()
],
devServer:
contentBase: "./dist",
hot: true,
historyApiFallback: true,
port: 4000
;
预期的行为是什么?
应该有一种方法可以从主包中排除 .json 文件。我试过 File-Loader、json-loader 和 const someJson = require(./someJson)
其他相关信息: 网络包版本:4.16.1 Node.js 版本:10.12.0
操作系统:Mac OS 10.14 Mojave
在下面回答(至少我是如何解决的)。如果没有任何数据,我无法初始化 lottie。
【问题讨论】:
尝试阅读延迟加载,也称为代码拆分,因此最终 JSON 将作为一个块加载,而不是在主包中。 You can leverage Webpack'simport
将 JSON 从您的主包中拆分出来。
【参考方案1】:
最终,我在下面得到了答案,但在没有任何 JSON 数据的情况下无法初始化 lottie。我最终这样做了:
import React, PureComponent from "react"
import Lottie from 'react-lottie'
export default class AnimationAutomatedCommunication extends PureComponent
constructor(props)
super(props)
this.state =
animation: <div />
async componentDidMount()
const animation = await import(/* webpackChunkName: "AnimationAutomatedCommunication" */ './JsonData/AnimationAutomatedCommunication.json')
const defaultOptions =
loop: true,
autoplay: true,
animationData: animation.default
this.setState(
animation: <div className=this.props.className>
<Lottie key="lottie-win-jobs" options=defaultOptions
isStopped=this.props.isStopped />
</div>
)
render()
return (
<React.Fragment>
this.state.animation
</React.Fragment>
)
【讨论】:
【参考方案2】:预期的行为是 JSON 将被捆绑,因为它可能在运行时同步需要。 JSON 数据不同于像图像文件这样由浏览器异步加载的数据,因为它们通过src
属性等呈现在页面上。
正如 cmets 所提到的,您应该使用代码拆分。如果您安装并使用@babel/plugin-syntax-dynamic-import
插件,最新版本的Webpack 支持dynamic imports。
npm install --save-dev @babel/plugin-syntax-dynamic-import
然后在babel.config.js
:
module.exports =
...
plugins: [
"@babel/plugin-syntax-dynamic-import"
]
...
;
示例
假设您有一个 React 组件,它可能需要一些 JSON 数据,但不需要将其作为捆绑包的一部分同步加载。您的 非 代码拆分版本可能如下所示:
import React from 'react';
import myJSON from './myJSON.json';
export default class MyComponent extends React.Component
render()
return <div>JSON.stringify(myJSON, null, 2)</div>
相反,您可以使用动态导入 - 基本上是运行时导入,它返回一个 Promise,您可以使用它来异步加载一些与您的包分开分块的数据:
import React from 'react';
import myJSON from './myJSON.json';
export default class MyComponent extends React.Component
state = data: ;
componentDidMount()
import(/* webpackChunkName: 'myJSON' */ './myJSON.json')
.then((data) =>
this.setState(data);
);
render()
return <div>JSON.stringify(this.state.data, null, 2)</div>
或者,您可以使用 React 的新 lazy
和 Suspense
API(v16.6.0 及更高版本)到 dynamically import React components,它们与捆绑包分开分块。如果您想将组件及其对应的 JSON 数据分块在一起,但与主包分开,这可能会更可取:
// MyComponent.jsx
import React from 'react';
import myJSON from './myJSON.json';
export default class MyComponent extends React.Component
render()
return <div>JSON.stringify(myJSON, null, 2)</div>
// SomeParent.jsx
import React, lazy, Suspense from 'react';
const MyComponent = lazy(() => import(/* webpackChunkName: 'MyComponent' */ './MyComponent'));
export default class SomeParent extends React.Component
render()
return <div>
<Suspense fallback=<div>Loading...<div> >
<MyComponent />
</Suspense>
</div>;
在上面的示例中,<MyComponent />
及其对应的代码(包括 JSON 数据)只会在组件在运行时实际呈现时才被加载。
【讨论】:
如果我不必用某种 JSON 数据初始化 react-lottie,那么您的答案将是完美的,不过我最终还是在代码库的其他地方使用了它,谢谢一个彻底的答复。 @GarrettJMU 您可以等待渲染react-lottie
组件,直到 JSON 数据加载完毕。在我发布的第三个代码块中,您可以看到如何动态加载 JSON 数据并在数据可用时使用 Promise.then()
对其进行处理。以上是关于使用 webpack 为 react-lottie 从主包中排除 JSON 文件的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 webpack 和 angular2 为生产部署代码
webpack学习笔记 webpack-dev-server插件和HotModuleReplacementPlugin插件使用