start
This chapter is about packaging volume optimization, which is also the most important one. I spent a lot of time looking up information about how to optimize packaging volume before. There are some differences between different versions of Webpack, so I have made a lot of mistakes, so this chapter will be quite long.
Here I have written a rough layout of the page. It looks like this:
yarn add webpack-bundle-analyzer -D
Copy the code
Add a line to the plugins in webpack.config.prod.js. Note that the ports can be modified to avoid collisions:
new BundleAnalyzerPlugin({ analyzerPort: 8081 })
Copy the code
After the modification is complete, run yarn run build command, in the browser pop-up window, mine looks like this:
1. Modify mode
Let’s go to webpack.config.prod.js:
//mode:'development'
mode:'production' // Change to production environment
Copy the code
Webpack will automatically optimize the package size, such as compress code and so on:
2. Antd is loaded on demand
Execute from the console:
yarn add babel-plugin-import -D
Copy the code
Then go to webpack.config.common.js to configure:
plugins:[
"@babel/plugin-transform-runtime"['import', {libraryName:'antd'.libraryDirectory: 'es'.style:true}]]Copy the code
In less configuration:
{
loader:'less-loader'.options: {javascriptEnabled: true}}Copy the code
Then we go to use the ANTD component and modify it to the following form:
// import Col from 'antd/lib/col';
// import Row from 'antd/lib/row';
// import "antd/dist/antd.css"; / / CSS is also removed
import {Col,Row} from 'antd'
Copy the code
Then execute the package command to change to 601KB:
3. Mini-css-extract-plugin Extracts CSS
We use mini-CSs-extract-plugin to separate CSS from JS. Execute from the console:
yarn add mini-css-extract-plugin -D
Copy the code
In webpack.config.prod.js:
// Introduce at the top
const MiniCssExtractPlugin=require('mini-css-extract-plugin');
// Add it to the plugins
new MiniCssExtractPlugin({/ / CSS
filename:'css/main.css'
}),
Copy the code
This way we can separate the CSS into a CSS folder. Then pack and see:
Optimize – CSS-assets-webpack-plugin is a plugin that compresses JS with the ability to optimize- CSS-assets-webpack-plugin with the ability to optimize- CSS-assets-webpack-plugin with the ability to optimize- CSS-assets-webpack-plugin
yarn add optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
Copy the code
We configure webpack.config.common.js:
// This configuration is the same as module and plugins
optimization:{
minimizer: [new UglifyJsPlugin({Js / / compression
cache:true.parallel:true.sourceMap:true
}),
new OptimizeCSSAssetsPlugin()/ / compress CSS]},Copy the code
Then we went to pack, and we found that the CSS had become smaller:
4. DllPlugin and DllReferencePlugin
As we can see from the previous packaging diagram, most of the package volume is occupied by the React family bucket and Babel. Now we will separate these into a JS file, because we will not change these things.
DllPLugin == webPack.config.dll. Js == in the root directory, and then configure it in the root directory.
const path=require('path')
const webpack =require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin');
// You only need to use yarn Run DLL once
module.exports={
mode:'production'.entry: {// Put the React stuff and Babel here
vendor:['react'.'react-dom'.'react-router-dom']},output: {filename:'dll/_dll_[name].js'.path:path.resolve(__dirname,'dist'),
library:'_dll_[name]'
},
plugins: [new webpack.DllPlugin({
name:'_dll_[name]'.path:path.resolve(__dirname,'dist/dll'.'mainfist.json')}),new CleanWebpackPlugin(['./dist/dll']),// Delete files in the DLL directory]}Copy the code
==webpack.config.common.js==
// Add it under plugins
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist/dll'.'mainfist.json')}),Copy the code
Then go to package.json.
// Add a new one under scripts
"dll": "webpack --config webpack.config.dll.js"
Copy the code
Execute from the console:
yarn run dll
Copy the code
// Add it at the end of the body
<script src="dll/_dll_vendor.js"></script>
Copy the code
Then run yarn Run build:
5. @babel/polyfill
As you can see in the previous diagram, core-js takes up a lot of volume, and this is the library that Babel/Polyfill uses. I offer two approaches here.
1.@baebl/ Polyfill is loaded on demand
We can use the useBuiltIns property, which is new to Babel7, and we need to configure it like this:
presets:[
[
'@babel/preset-env',
{
"targets": {
"browsers": [
"ie >=9"."last 2 version"."5%" >."not dead"]},"useBuiltIns":"usage"}].'@babel/preset-react'].Copy the code
When configured this way, we can add the index.js top
//import '@babel/polyfill' // drop this line
Copy the code
Then we package and execute YARN Run Build:
2. To extract @ baebl/polyfill
The second way, we can extract @babel/polyfill directly, just like the React family bucket. We go to ==webpack.config.dll. Js == to configure:
/ / add @ Babel/polyfill
vendor:['react'.'react-dom'.'react-router-dom'.'@babel/polyfill']
Copy the code
Then go to the top of index.js and add:
import '@babel/polyfill'
Copy the code
Then we run the YARN Run DLL, and we can see that vendor’s package is larger:
6. React router load dynamically
We used to load all the components on the page, so that the components we didn’t click on would load, which would lead to waste. It is much better to use dynamic loading to load components that are clicked on.
We execute on the console:
yarn add react-loadable babel-plugin-syntax-dynamic-import -D
Copy the code
==webpack.config.common.js==
plugins:[
"@babel/plugin-transform-runtime".'babel-plugin-syntax-dynamic-import'.// Add this line
['import', {libraryName:'antd'.libraryDirectory: 'es'.style:true}]]Copy the code
Then we go to the place where routing is used:
import Loadable from 'react-loadable';// Note the addition of this line
// import A from '.. /pages/A/A'
// import B from '.. /pages/B/B'
// Write it like this
const A = Loadable({
loader: (a)= > import('.. /pages/A/A'),
loading:(a)= > {
return <div>Loading...</div>}});const B = Loadable({
loader: (a)= > import('.. /pages/B/B'),
loading:(a)= > {
return <div>Loading...</div>}});Copy the code
Then execute the package command and view:
We can see the effect:
This is what the page looks like when it first loads
Index. js volume interpretation
Here’s a bit more about the packaged graph. I actually wrote very little code under SRC, but there is an index.js in the packaged graph that is nearly 90KB in size. Why is this? We can try it. Here’s the code for most antD components I use on my home page:
<div>
<Header/>
<Row>
<Col xs={24} sm={24} md={6} lg={4} xl={4} xxl={4}>
<Aside/>
</Col>
<Col xs={24} sm={24} md={18} lg={20} xl={20} xxl={20}>
<div className="content">
{this.props.children}
</div>
</Col>
</Row>
</div>
Copy the code
We comment out all antD components we use, leaving only the Header:
//import {Col,Row} from 'antd' <div> <Header/> {/*<Row>*/} {/*<Col xs={24} sm={24} md={6} lg={4} xl={4} xxl={4}>*/} {/*<Aside/>*/} {/*</Col>*/} {/*<Col xs={24} sm={24} md={18} lg={20} xl={20} xxl={20}>*/} {/*<div className="content">*/} {/*{this.props.children}*/} {/*</div>*/} {/*</Col>*/} {/*</Row>*/} </div>Copy the code
Then we go to pack:
7. splitChunks
Then we separate third-party libraries like ANTD from the main package.
We configure it in optimization == webPack.config.common.js ==, at the same level as we did before we wrote js and CSS compression ==minimizer== :
splitChunks:{
cacheGroups: {vendors: {//node_modules
test:/[\\/]node_modules[\\/]/.chunks: "initial".name:'vendors'.//chunks name
priority:10./ / priority
enforce:true}}}Copy the code
Then execute the package command:
Although ANTD’s components are large, they are packaged only once, and can be reduced by more than a third with gZIP configured on the server, which is acceptable.
At the end
We ended up optimizing the main package size from 2.75M to around 5KB, but we were actually breaking up a large package into smaller packages and extracting common code.
In fact, there is another optimization method using externals, and then using CDN to introduce, but I have already used DllPlugin, do not use that method, you can use the two methods reasonably.
This chapter is too much stuff, and a little bit messy, but it should be quite detailed, but I think there is more to webPack volume optimization than that, if you have other ways to optimize, let me know, thanks.
Github address: github.com/xw-Zhou/web…
(PS: If there are any mistakes in this article, please point them out in the comments, thanks)