preface
Summary of their own performance optimization and webpack optimization. The current article describes Webpack, and the performance before Webpack will be summarized in the future.
The overall brain map is as follows:
Primary analysis: Use stats built into WebPack
Use stats in package.json
"Scripts ": {"stats": "webpack --json > stats.json"}, NPM run stats to produce the stas.json file, which contains the build statisticsCopy the code
Speed analysis: use speed-measure-webpack-plugin
The built-in STAS analysis of Webpack is coarse and difficult to find problems in file size and construction speed. The speed-measure-webpack-plugin can be used to analyze the time consumption of each loader and plugin
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const webpackConfig = smp.wrap({
plugins: [new MyPlugin(), new MyOtherPlugin()],
});
Copy the code
Volume analysis: Use Webpack-bundle-Analyzer to analyze volumes
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
Copy the code
Performance improvement methods (for build speed and volume optimization)
Use older versions of WebPack and Node.js
When webpack4 first came out, compared to webpack3 on twitter, webpack4’s build time was reduced by 60-98%
Reasons for using WebPack4:
-
V8 optimizations (for of instead of forEach, Map and set instead of Object, includes instead of indexOf)
-
The default is to use the faster MD4 hash algorithm instead of MD5
-
Webpacks AST can be passed directly from the Loader to the AST, reducing parsing time
-
Use string methods instead of regular expressions
Multi-process, multi-instance: Parse builds
Options:
- Thread-loader (Official)
- parallel-webpack
- HappyPack
Use HappyPack to parse resources Every time WebPack parses a module, HappyPack assigns it and its dependencies to worker threads webpack-happyLoader-happyPlguin -happyThreadPool-happyThread [1…N] – HappyWorkerChannel[1…N] – HappyWorker[1..N] (HappyPack workflow)
Use thread-loader to parse resources
How it works: As with HappyPack, each time webPack parses a module, Thread-Loader assigns it and its dependencies to worker threads
module.exports = {
module: {
rules: [
{
test: /\.js$/,
include: path.resolve('src'),
use: [
'thread-loader',
// your expensive loader (e.g babel-loader)
],
},
],
},
};
Copy the code
If you need to configure three-Loader, you can configure it in the form of configuration items
use: [ { loader: 'thread-loader', // loaders with equal options will share worker pools options: { // the number of spawned workers, defaults to (number of cpus - 1) or // fallback to 1 when require('os').cpus() is undefined workers: 2, // number of jobs a worker processes in parallel // defaults to 20 workerParallelJobs: 50, // additional node.js arguments workerNodeArgs: ['--max-old-space-size=1024'], // Allow to respawn a dead worker pool // respawning slows down the entire compilation // and should be set to false for development poolRespawn: false, // timeout for killing the worker processes when idle // defaults to 500 (ms) // can be set to Infinity for watching builds to keep workers alive poolTimeout: In 2000, // number of jobs the poll distributes to the workers // defaults to 200 // decrease of less efficient but more fair distribution poolParallelJobs: 50, // name of the pool // can be used to create different pools with elsewise identical options name: 'my-pool', }, }, // your expensive loader (e.g babel-loader) ];Copy the code
Multi-process, multi-instance: parallel compression
Method 1: Use the parallel ugliffe -plugin
Uglifyjs-webpack-plugin enables parallel (recommended before WebPack 4.0)
Terser-webpack-plugin enables parallel (recommended)
module.exports = { optimization: { minimize: true, minimizer: [ new TerserPlugin({ parallel: True, // parallel defaults to 2 times the number of cpus in the current computer environment minus 1}),],},};Copy the code
If you are using WebPack V5 or above, you do not need to install this plugin. Webpack V5 comes with the latest Terser-webpack-plugin. If you use Webpack V4, you must install the version of Terser-webpack-Plugin V4
Further subcontracting: precompile resource modules
Method 1: use html-webpack-externals-plugin (e.g. React/react-dom base package via CDN)
Method 2: Use SplitChunksPlugin
Method 3: Use DLLPlugin for subcontracting, DIIReferencePlugin to Mainfest.json (official built-in plugin)
Generally, the webpack.dll. Js file is created to subcontract public base packages and service base packagesThen in webpack. Config. Js through webpack. DllReferenctPlugin for reference
Make full use of cache to improve secondary build speed
Objective: To improve the speed of secondary construction
- Babel-loader enables caching
- Terser-webpack-plugin enables caching
- Use cache-loader or hard-source-webpack-plugin
Narrow your Build goals
Purpose: Build as few modules as possible such as babel-loader that does not resolve node_modules
Reduce file search scope
- Optimize the resolve.modules configuration (reduce the module search hierarchy)
- Optimize the resolve.mainfields configuration
- Optimize the resolve.extensions configuration
- Use aliases wisely (mark yourself as a good alias)
Use Tree Shaking to erase useless JavaScript and CSS
About the tree shaking
Concept: A module may have multiple methods, and as long as one of them is used, the whole file will be sent to the bundle. Tree shaking is simply putting used methods into the bundle, while unused methods are erased during the Uglify phase.
Use: Webpack by default. Babelrc sets modules: false to production mode by default
Requirements: must be ES6 syntax, CJS methods do not support
Erase useless CSS
Use purgecss-Webpack-Plugin and mini-CSS-extract-Plugin together
const path = require('path'); const glob = require('glob') const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin'); const smp = new SpeedMeasureWebpackPlugin(); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const TerserPlugin = require("terser-webpack-plugin"); const webpack = require('webpack'); const PurgeCSSPlugin = require('purgecss-webpack-plugin') const PATHS = { src: Path. The join (__dirname)} module. Exports = SMP. Wrap ({/ / developer tools Don't need to develop a debugging devtool: false, / / development mode for code compression mode: 'development', // entry file entry: './index.js', output: {// output filename filename: 'bundle.js', // output file path: Path. The join (__dirname, '/'),}, the module: {rules: [{/ / regular matching suffix called CSS file test: / \. CSS $/, use: [MiniCssExtractPlugin.loader, 'css-loader'], } ] }, plugins: [ new MiniCssExtractPlugin(), new PurgeCSSPlugin({ paths: Glob. Sync (` ${PATHS. SRC} / * `, {nodir: true}), / / support only absolute path}),]});Copy the code
Use the dynamic Polyfill service
Use Webpack for image compression
Use image-Webpack-loader air tickets
Volume optimization strategy summary
- scope Hoisting
- Tree-shaking
- Separation of common resources
- Image compression
- Dynamic polyfill