Why performance tuning
When using Webpack, if you do not pay attention to performance optimization, you may have performance problems, which will lead to a not very silky development experience. Performance problems are mainly slow compilation speed and large packaging volume, so performance optimization is mainly analyzed in these aspects. This article is mainly their usual work accumulation and reference to other people’s articles, and summarize, based on Webpack4 version.
Build analysis
Compile speed analysis
The first task of optimizing Webpack build speed is to know where to look. The speed-measure-webpack-plugin can measure the webpack build speed
SMP ⏱ General output time took 38.3 secs SMP ⏱ Plugins HtmlWebpackPlugin took 1.31 secs CopyPlugin took 0.016 secs OptimizeCssAssetsWebpackPlugin took 0.002 secs ContextReplacementPlugin took 0.001 secs MiniCssExtractPlugin took 0 secs DefinePlugin took 0 secs SMP ⏱ Loaders [email protected]@babel-loader took 29.98 secs module count = 1503 _babel - [email protected] @ Babel - loader, And [email protected]@eslint-loader took 18.74 secs module count = 86 [email protected] @CSS-loader, And [email protected]@less-loader took 16.45 secs module count = 64 modules with no loaders took 2.24 secs module count = 7 [email protected]@file-loader took 1.03 secs module count = 17 [email protected]@style-loader, And _css - [email protected] @ CSS - loader, And [email protected]@less-loader took 0.102 secs module count = 64 [email protected]@html-webpack-plugin took 0.021 secs Module count = 1Copy the code
It achieved an impressive 38.3 seconds, which was a bit imprecise, but very slow. Babel-loader, ESlint-loader, CSS-loader, and less-loader occupy the majority.
const webpackBase = require('./webpack.base.conf'); const path = require('path'); const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin'); const smp = new SpeedMeasureWebpackPlugin(); Module.exports = smp.wrap({// set source code display mode devtool: 'eval-source-map', mode: 'development', entry: {app: ['./src/index.jsx'] }, output: { path: path.resolve(__dirname, 'dist'), filename: 'index.js' }, resolve: webpackBase.resolve, module: webpackBase.module, stats: webpackBase.stats, optimization: webpackBase.optimization, plugins: [ webpackBase.plugins.html, webpackBase.plugins.miniCssExtract, webpackBase.plugins.optimizeCssAssets, // webpackBase.plugins.progressBarPlugin, webpackBase.plugins.ContextReplacementPlugin, webpackBase.plugins.DefinePlugin, // webpackBase.plugins.AntdDayjsWebpackPlugin, webpackBase.plugins.CopyPlugin // webpackBase.plugins.HotModuleReplacementPlugin ], devServer: webpackBase.devServer, watchOptions: webpackBase.watchOptions, externals: webpackBase.externals });Copy the code
Package volume analysis
The webpack-bundle-Analyzer plugin can generate a build volume report after a Webpack build is complete. With a visual page, you can intuitively know the specific volume occupied in the build.
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: bundleAnalyzer: new BundleAnalyzerPlugin({ analyzerPort: 8081 })],
};
Copy the code
The renderings are as follows:
One obvious problem is Ant Design, TRTC, Mobx libraries.
Packing volume is as follows:
How to optimize
Narrow your Build goals
- To optimize the
resolve.modules
Configuration (reduces module search levels and unnecessary compilation work) - To optimize the
resolve.extensions
configuration - Increase the cache
const path = require('path'); Module. exports = {resolve: {// Automatically resolve extensions: ['.js', '.jsx', '.css', '.less', '.json'], alias: {// create an alias for import or require to ensure module introduction becomes simpler 'react': Path. The resolve (__dirname, '. / node_modules/react/dist/react. Min. Js')}, / / when the NPM package import module, This option will determine which fields are used to import modules in' package.json '// The default is browser -> module -> main mainFields: ['main']}, module: {rules: [{/ / exclude node_modules module test: / \. (js | JSX) $/, exclude: / node_modules /, / / open the buffer loader: 'babel-loader?cacheDirectory=true' } ] } };Copy the code
Enable multiple processes by using thread-loader
Thread-loader will run your loader in a pool of workers, each of which is a separate node.js process with a 600ms limit. Data exchange across processes is also limited. Use it in a high-overhead loader; otherwise, the effect is poor.
module.exports = {
module: {
rules: [
{
test: /\.js$/,
include: path.resolve('src'),
use: [
'thread-loader',
// your expensive loader (e.g babel-loader)
],
},
],
},
};
Copy the code
Use the hard – source – webpack – the plugin
In Webpack4, the hard-source-webpack-plugin is a better alternative to DLLS.
Hard-source-webpack-plugin is a plug-in for Webpack that provides an intermediate caching step for modules. To see the results, you need to run Webpack twice with this plug-in: the first build will take a normal amount of time. The second build will be significantly faster (approximately 90% faster build speed). However, the plugin has not been updated for a long time and is not recommended.
Remove eslint – loader
Since I’m using eslint-Loader in my project, I can remove it if PREcommit is configured.
Exclude related packages via externals
Webpack
Module.exports = {externals: {react: 'react ', 'react-dom': externals: {react: 'react ', 'react-dom': 'ReactDOM', 'trtc-js-sdk': 'TRTC', bizcharts: 'BizCharts', antd: 'antd', mobx: 'mobx', 'mobx-react': 'mobxReact' } };Copy the code
index.html
<! DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" /> <meta name="baidu-site-verification" content="ptk9VJudKz" /> <link rel="stylesheet" A href = "https://xxx/antd.min3.26.20.css" / > < title > webpack < / title > < script type = "text/javascript" SRC = "https://xxx/17.0.0react.production.min.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/17.0.0react-dom.production.min.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/BizCharts3.5.8.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/trtc4.6.7.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/moment2.29.1.min.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/moment2.29.1zh-cn.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/polyfill.min7.8.0.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/antd.min3.26.20.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/mobx.umd.min5.13.1.js" > < / script > < script type = "text/javascript" SRC = "https://xxx/mobx-react.index.min5.4.4.js" > < / script > < / head > < body > < div id = "root" > < / div > < / body > < / HTML >Copy the code
JS compressed
Starting with Webpack4, terser is used by default to compress output in production. Terser is an ES2015 + compatible JavaScript compressor. Compared to UglifyJS, an early standard for many projects, it is a future-oriented choice. There was a branch of UglifyJS, uglip-es, but since it was no longer maintained, a separate branch was born from this branch, terser.
const TerserPlugin = require('terser-webpack-plugin'); Module. Exports = {optimization: {minimizer: [/ js/compression new TerserPlugin ({test: / \. (JSX | js) $/, extractComments: true, parallel: true, cache: true }) ] }, };Copy the code
CSS compression
After Webpack 4.0, it is recommended to use the mini-CSs-extract-plugin to package CSS files.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(css|less)$/,
use: [MiniCssExtractPlugin.loader]
}
]
},
};
Copy the code
FAQ
Ant Design could not load
Make sure that Moment and Polyfill are loaded before Ant Design
MobX cannot load
MobX introduced the mobx.umd.min.js library, which mobx-React needed to introduce
package.json
{" name ":" webpack ", "version" : "1.0.0", "private" : true, "main" : "index. Js", "dependencies" : {" antd ": "^ 3.26.20", "Babel - eslint" : "^ 10.0.3", "Babel - loader" : "^ 8.0.0", "Babel - plugin - import" : "^ 1.13.0", "Babel - plugin - react - CSS - modules" : "^ 5.2.6", "bizcharts" : "^ 3.5.8", "China - division" : "^ 2.3.1," "compression will webpack - plugin" : "^ 3.0.1", "copy - webpack - plugin" : "^ 5.1.1", "CSS - loader" : "^ 3.2.0", "eslint" : "^ 6.8.0 eslint - config -", "prettier" : "^ 6.11.0", "eslint - config - standard" : "^ 14.1.0", "eslint - loader" : "^ 3.0.4 eslint - plugin -", "import" : "^ 2.20.0", "eslint - plugin - promise" : "^ 2", "eslint - plugin - react" : "^ 7.17.0 eslint - plugin -", "standard" : "^ 4.0.1", "HTML - webpack - plugin" : "^ 3.2.0", "less" : "^ 3.8.1", "less - loader" : "^ 5.0.0 lint -", "staged" : "^ 10.0.8", "mini - CSS - extract - the plugin" : "^ 0.8.0", "mobx" : "^ 5.13.1", "mobx - react" : "^ 5.4.4," "optimize - CSS - assets - webpack - plugin" : "^ 5.0.1", the "pre - commit" : "^ 1.2.2", "progress - bar - webpack - plugin" : "^ 1.12.1" and "react", "^ 17.0.0", "the react - dom" : "^ 17.0.0", "speed - measure - webpack - plugin" : "^ 1.3.1", "style - loader" : "^ 1.2.1 terser - webpack -", "plugins" : "^ 2.2.1", "the TRTC - js - SDK" : "^ 4.6.7", "viewerjs" : "^ 1.5.0", "webpack" : "^ 4.41.2 webpack", "- a bundle - analyzer" : "^ 3.6.0", "webpack - cli" : "^ 3.3.10", "webpack - dev - server" : "^ 3.10.1"}}Copy the code
The final result
Packing volume:
The packing volume has changed from 2.1m to 882KB, which is a huge effect.
Package:
Ant Design, TRTC, Mobx libraries are also gone
Compilation speed:
SMP ⏱ General output time took 10.67 secs SMP ⏱ Plugins HtmlWebpackPlugin took 1.69 secs BundleAnalyzerPlugin took 0.091 Secs CopyPlugin took 0.011 secs MiniCssExtractPlugin took 0.003 secs OptimizeCssAssetsWebpackPlugin took 0.002 secs DefinePlugin took 0.001 secs ContextReplacementPlugin took 0 secs SMP ⏱ Loaders [email protected]@babel-loader took 8.26 secs module count = 277 [email protected]@babel-loader, And [email protected]@eslint-loader took 7.18 secs module count = 86 [email protected] @CSS-loader, And [email protected]@less-loader took 1.94 secs module count = 28 modules with no loaders took 0.728 secs module count = 12 [email protected]@file-loader took 0.392 secs module count = 17 [email protected]@style-loader, And _css - [email protected] @ CSS - loader, And [email protected]@less-loader took 0.052 secs module count = 28 [email protected]@html-webpack-plugin took 0.026 secs module count = 1Copy the code
The compile speed has been reduced from 38.3 secs (15 seconds) to 10.67 secs (10 seconds).
Public CDN addresses at home and abroad
- BootCDN
- cdnjs
The resources
- Webpack Guidebook
- What is the core knowledge of Webpack?
blog
blog