preface
In the previous Webpack tutorial, we talked about the basic build of the webpage packaging project, which tells you how to compress JS and CSS files. This can actually be seen as part of the volume optimization of the project, which is further studied below.
Note: The following features are based on Webpack version ^4.43.0 debugging.
The quantitative analysis of
In the base build, we combined project code and third-party code into a bundle. If we need to optimize this file, the idea should be to delete and merge the modules in it (duplicate content).
So, first we need to know the size of each bundle template. In this case, we need to use the plugin Webpack-Bundle-Analyzer, which outputs an interactive visual tree showing the size of the bundle.
Note: Can also be usedwebpack --profile --json > stats.json
Command (not recommended for this scheme) in the generatedstats.json
In the viewbundle
File size can also be inOfficial analysis toolsAnalysis in
// webpack.prod.config.js
const baseWebpackConfig = require('./webpack.base.config');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
constwebpackConfig = merge(baseWebpackConfig, { ... .plugins: [
newBundleAnalyzerPlugin(), ... ,]})module.exports = webpackConfig;
Copy the code
This way, when we executenpm run build
After the command is executed, it is openedhttp://127.0.0.1:8888/
:
In this way, we can intuitively analyze which file has the largest volume and which module has the largest volume.
File compression
When we need to optimize volume processing, the initial thought is usually to compress files. In this project, in addition to using gzip to compress files, Webpage also compresses JS, CSS, and HTML files. (Refer to the basics of development in the previous article.)
- Js file, Settings
mode
The value ofproduction
Webpage will automatically compress - The CSS file, use the plug-in CssMinimizerWebpackPlugin
- HTML file, Settings
mode
The value ofproduction
Webpage will automatically compress - Images, using the image-webpack-loader plug-in automatically compressed images
Resolution of the code
CDN
In real projects, we can see that third-party libraries account for a large proportion of the resulting bundle files. We can configure externals to extract the third library commonly used in it (such as Vue, VUe-Router, vuex, etc.), place it in the CDN, and introduce it through
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous">
</script>
Copy the code
// webpack.prod.config.js
module.exports = { ... .externals: {
// jquery, where key is the name of the third-party library introduced in the project logic code
// jQuery, for value, represents global variables introduced through script
jquery: 'jQuery'}};// Project logic code
import $ from 'jquery'; .Copy the code
To prevent the repeat
The SplitChunksPlugin plug-in can extract a common dependency module into an existing Entry chunk or into a newly generated chunk.
Webpack will automatically split code blocks based on the following criteria:
- New code blocks are shared or come from the node_modules folder
- New code block larger than 30KB (before min+giz)
- The number of requests to load code blocks on demand should be <=5
That is, no more than five requests can be sent to load chunk.
For example: A. js relies on four files: 1.js, 2.js, 3.js, 4.js, which satisfy the first two criteria for code splitting (shared and larger than 30KB). In this case, five chunks are divided: A.chunk. js, 1.chunk.js, 2.chunk.js, 3.chunk.js, and 4.chunk.js. In this case, the number of concurrent requests for loading chunk~ A is exactly 5.
If A.js relies on 5.js again, 5.chunk will not be split, because if a.chunk is split, there will be 6 requests for loading A.hunk, and the contents of 5.js will be merged into A.hunk.
-
The number of requests to load code blocks at page initialization should be <=3
The logic here and the type above are just for entry.
In addition, the default configuration is provided under splitChunks under Optimization (see here for detailed configuration instructions) :
// webpack.config.js
module.exports = {
/ /...
optimization: {
splitChunks: {
chunks: 'async'.// This indicates which blocks will be selected for optimization. "Initial" | "all" (recommended) | "async" (the default) | function
minSize: 30000.// The minimum size of the generated block in bytes
maxSize: 0.minChunks: 1.// The minimum number of blocks that must be shared before splitting
maxAsyncRequests: 5.// Maximum number of parallel requests when loading on demand
maxInitialRequests: 3.// The maximum number of parallel requests for the entry page
automaticNameDelimiter: '~'.By default, Webpack will generate names using the source and name of the block (vendors~main.js, for example). This option allows you to specify the delimiter used to generate the name.
name: true.// The name of the split block. boolean: true | function (module, chunks, cacheGroupKey) | string
cacheGroups: { // This is where the chunks cache group is set. SplitChunks are split according to the cacheGroups
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2.priority: -20.reuseExistingChunk: true}}}}};Copy the code
Dynamic import
Webpack provides two similar techniques when it comes to dynamic code splitting. The first, and recommended option, is to implement dynamic imports using the import() syntax that conforms to the ECMAScript proposal. The second, which is a webPack legacy, uses webPack-specific require.ensure.
Here we use the first scheme for dynamic introduction. Its introduction method is as follows:
import(/** webpackChunkName: "lodash" **/ 'lodash').then(_= > {
// doSomething
})
Copy the code
Next, we need to modify the WebPack configuration by adding chunkFilename:
// webpack.config.js
module.exports = {
output: {
filename: '[name].bundle.js',
+ chunkFilename: '[name].bundle.js'.// [name] is the value of webpackChunkName when you import
path: path.resolve(__dirname, 'dist')}};Copy the code
Other optimization
tree-shaking
If you use ES6’s import syntax, unused code is automatically removed in a production environment.
// utils.js
const add = (a, b) = > {
return a + b;
}
const minus = (a, b) = > {
return a - b;
}
export {
add,
minus
}
//index.js
import {add, minus} from './utils';
add(1.2);
Copy the code
In a project, minus is not built into bundles.
Scope Hosting scope improved
JavaScrct has function promotion and variable promotion, which promote function and variable declarations to the top of the current scope. Scope Hosting in Webpack is similar, upgrading modules.
Scope Hosting will analyze the dependencies between modules and merge the separated modules into a function as much as possible, thus reducing the cost of introducing modules. But the premise is not to create code redundancy, so only those modules that have been referenced once can be merged.
// webpack.config.js
module.exports = {
plugins: [new webpack.optimize.ModuleConcatenationPlugin()],
};
Copy the code
As Scope needs to analyze the dependencies between modules, the source code must adopt ES6 modular statement, or it will not take effect.
Dynamic Polyfill service
Babel is only responsible for syntax conversion, such as converting ES6 syntax to ES5. However, if there are objects or methods that the browser does not support, for example:
- Global objects: Promise, WeakMap, etc.
- Global static functions: array. from, Object.assign, etc.
- Example methods: array.prototype.includes, etc.
At this point, babel-Polyfill is introduced to simulate the implementation of these objects and methods, commonly known as shippers.
Babel-polyfill imports the entire polyfill at one time, resulting in a large file, so we use the dynamic Polyfill service for optimization.
Each time a page is opened, the browser sends a request to the Polyfill Service, which recognizes the User Agent and delivers a different Polyfill to load the effect of the Polyfill on demand.
reference
- A Brief Introduction to Webpack Performance Optimization
- Code Splitting Webpack Details
- Configuration SplitChunksPlugin
- Lin Dull webpack road – optimization chapter
- 9 Webpack Optimization Strategies you may not know