We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Code Splitting (代码分隔)可以将代码分隔到不同的bundle中,然后可以按需加载或者并行加载这个文件。从而在网页加载时获得更好的加载体验。 该文章主要以实践为主,因为之前自己在配置这方面折腾的比较少,😑😑
首先简单搭建下webpack开发配置:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') .BundleAnalyzerPlugin; module.exports = { entry: { index: './src', another: './src/another.jsx', }, output: { filename: '[name].js', chunkFilename: '[name].js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, ], }, resolve: { extensions: ['.js', '.jsx', '.css'], }, optimization: { splitChunks: {}, }, plugins: [ new CleanWebpackPlugin(), new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src/index.html'), }), ], };
开发目录如下:
index.jsx:
import React from 'react'; import ReactDOM from 'react-dom'; import moment from 'moment'; import App from './App'; ReactDOM.render(<App />, document.getElementById('root'));
anathor.jsx:
import React from 'react'; import ReactDOM from 'react-dom'; import Container from './components/container'; ReactDOM.render(<Container />, document.getElementById('root'));
App.jsx:
import React from 'react'; import Container from './components/container'; export default function App() { return ( <div> <Container /> </div> ); }
container.jsx:
import React from 'react'; import moment from 'moment'; export default function Container() { return <div>容器</div>; }
Selector.jsx:
import React from 'react'; import { Select } from 'antd'; const { Option } = Select; const mapStateToProps = rootState => { return { global: rootState.global }; }; function RegionSelect(props) { const { global } = props; return ( <div className="region-select"> <span>选择大区</span> <Select value={global.region} onChange={handleSelectChange} style={{ width: 104 }}> <Option value="all">全部</Option> <Option value="east">东区</Option> <Option value="south">南区</Option> <Option value="west">西区</Option> <Option value="north">北区</Option> </Select> </div> ); } export default RegionSelect;
现在直接跑 npm run build(webpack --mode production),看下打包情况:
npm run build(webpack --mode production)
可以看出公共的依赖包并没有被单独拿出来,这时我们需要依靠 SplitChunksPlugin 来做这件事,而webpack 已内置了 SplitChunksPlugin,并且给设定了初始配置:
SplitChunksPlugin
splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } }
上面的每个字段的意思参见Webpack4之SplitChunksPlugin。因为 chunks 被设置为了 async,所以只对动态加载的文件进行分块。这里我们先将其改成 all
async
all
相较于之前,moment与react相关代码已被单独成包了。 但现在如果我想吧react以及react-dom单独拿出来呢?我们可以设置一个 cacheGroup:
moment
react
cacheGroup
splitChunks: { chunks: 'all', cacheGroups: { react: { test: (module, chunks) => /react/.test(module.context), priority: 1, }, }, },
好,react相关代码也被单独拿出来了,,这时可能会问,为何react的代码不会被放到vendors中呢?这时因为 react这个cacheGroup的优先级(1)大于vendors的优先级(-10)。 之前我们讲到,chunks的默认值为 async,现在我们来试试该效果,在another.jsx引入如下代码,然后不设置splitChunks:
(1)
-10
chunks
another.jsx
splitChunks
import(/* webpackChunkName:"antd" */ './components/Selector');
看的出来,,antd 被单独打包了,而moment还是在各个入口文件中各有一份,此时在设置为all试试:
如果我们一开始就加载整个应用的代码,那会在首页即加载很多无关的代码,所以我们可以按照路由级别来按需加载相关代码。 通过上面的了解,我们可以对每个路由对应的组件使用 import() 这个方法来动态引入,然后webpack会根据此来分隔代码,从而实现按需加载。 但是 import() 方法返回的是一个 Promise,并不能直接给react-router 来使用,所以我们需要一个组件。可以想一下,我们封装一个 加载组件,在组件未加载完成时,给个loading来提示,设置一个state,在组件加载好后,setState一下,不就ok 了? 可以看看 umi/dynamic,它是基于 react-loadable来实现的,而 react-loadable 的大致思路也是上面我说的这种。
import()
Promise
react-router
umi/dynamic
react-loadable
SplitChunksPlugin Webpack Code Splitting
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Code Splitting (代码分隔)可以将代码分隔到不同的bundle中,然后可以按需加载或者并行加载这个文件。从而在网页加载时获得更好的加载体验。
该文章主要以实践为主,因为之前自己在配置这方面折腾的比较少,😑😑
SplitChunksPlugin
首先简单搭建下webpack开发配置:
开发目录如下:
index.jsx:
anathor.jsx:
App.jsx:
container.jsx:
Selector.jsx:
现在直接跑
npm run build(webpack --mode production)
,看下打包情况:可以看出公共的依赖包并没有被单独拿出来,这时我们需要依靠
SplitChunksPlugin
来做这件事,而webpack 已内置了 SplitChunksPlugin,并且给设定了初始配置:上面的每个字段的意思参见Webpack4之SplitChunksPlugin。因为 chunks 被设置为了
async
,所以只对动态加载的文件进行分块。这里我们先将其改成all
相较于之前,
moment
与react
相关代码已被单独成包了。但现在如果我想吧react以及react-dom单独拿出来呢?我们可以设置一个
cacheGroup
:好,react相关代码也被单独拿出来了,,这时可能会问,为何react的代码不会被放到vendors中呢?这时因为
react
这个cacheGroup
的优先级(1)
大于vendors的优先级(-10
)。之前我们讲到,
chunks
的默认值为async
,现在我们来试试该效果,在another.jsx
引入如下代码,然后不设置splitChunks
:看的出来,,antd 被单独打包了,而moment还是在各个入口文件中各有一份,此时在设置为
all
试试:关于react路由动态加载
如果我们一开始就加载整个应用的代码,那会在首页即加载很多无关的代码,所以我们可以按照路由级别来按需加载相关代码。
通过上面的了解,我们可以对每个路由对应的组件使用
import()
这个方法来动态引入,然后webpack会根据此来分隔代码,从而实现按需加载。但是
import()
方法返回的是一个Promise
,并不能直接给react-router
来使用,所以我们需要一个组件。可以想一下,我们封装一个 加载组件,在组件未加载完成时,给个loading来提示,设置一个state,在组件加载好后,setState一下,不就ok 了?可以看看
umi/dynamic
,它是基于 react-loadable来实现的,而react-loadable
的大致思路也是上面我说的这种。未完待续......
参考
SplitChunksPlugin
Webpack Code Splitting
The text was updated successfully, but these errors were encountered: