The sea is wide by diving, the sky is high as birds fly. Hey how are you! I’m Ed Qin. π
The previous article introduced the basic configuration of WebPack (portal πππ). Now let’s talk about how we can improve our project build performance by optimizing configuration items.
What should be optimized?
From the actual project perspective, we are more concerned about from project development to release online. Therefore, optimization items can be divided into the following dimensions:
- The development environment
- Optimize the performance of code execution
- Optimized code debugging
- Production environment optimization
- Optimize code packaging build speed
- Optimize the performance of code execution
Optimize the performance of code execution (development environment)
Development server devServer
In the development environment, the main reason is for the code to be friendly to run and easy to debug, so we need to use devServer to start a local service, let the code run.
DevServer is used for project automation (auto-compile, auto-open browser, auto-refresh browser, etc.). The build package will only be compiled in memory and will not be exported. Instead, the build package will be stored in memory and deleted automatically after closing.
You need to download the package to start the development server devServer
npm i -D webpack-dev-server
Copy the code
Write the base server configuration items
DevServer: {// contentBase: resolve(__dirname, 'dist'), // port: 3000, // open: true,},Copy the code
After the configuration is complete, I can start the project. My Webpack is installed in the project dimension, so I use NPX to run it
NPX webpack will output the packing result. In the dist folder, NPX webpack-dev-server will only compile the packing in memory, with no outputCopy the code
HMR (Module hot replacement)
HMR: Hot module replacement, responsive to file changes in a timely manner to the page, freeing F5 manual refresh.
Simply set hot to true in devServer to automatically enable HMR
DevServer: {// enable HMR hot: true}Copy the code
HMR Support files:
-
Style files: You can use the HMR function. Style-loader implements the hot module replacement function by default
-
Js file: HMR function cannot be used by default
If you modify a JS module, all JS modules will be refreshed, which obviously leads to inefficient hot replacement. We need to modify the entry JS file code so that one module changes and only that module is rebuilt, not all of them.
If (module.hot) {// If module.hot is true, HMR is enabled. Module.hot.accept ('./print.js', function() {// the method listens for changes in the print.js file. If changes occur, only this module will be repackaged. Print (); print(); }); }Copy the code
- HTML files: the HMR function is disabled by default
Note: HTML files cannot be hot-replaced using HMR. You can modify the entry entry to introduce HTML files
entry: ['./src/index.js', './src/index.html']
Copy the code
Optimized code debugging (development environment)
Extract CSS into a separate file
The CSS-loader integrates CSS files into JS files, causing the following impacts:
1: JS file size will be large
2: you need to load JS first and then dynamically create style tags, style rendering speed is slow
Solution: use MiniCssExtractPlugin. Alternative style – loader loader, extraction of js CSS into a single file
The mini-CSS-extract-plugin needs to be introduced
npm i -D mini-css-extract-plugin
Copy the code
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
{
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
],
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/main.css'
}),
]
}
Copy the code
CSS Compatibility
During development, we were writing some advanced styles that were not supported in older browsers, so we needed to introduce some loaders to help us solve this problem.
Postcss-loader postCSs-preset -env needs to be imported
npm i -D postcss-loader postcss-preset-env
Copy the code
// webpack.config.js
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require('postcss-preset-env')(),
],
},
},
Copy the code
After importing the loader, you also need to define browserslist in package.json
// package.json "browserslist": { [// Based on specific business scenarios, Match different browsers "last 1 Chrome version", "last 1 Firefox version", "last 1 Safari version"], // Production environment "production": [// compatible with most browsers ">0.2%", "not dead", "not op_mini all"]},Copy the code
Js Compatibility processing
In order to be compatible with older generation browsers, js also needs to be compatible.
Need to introduce babel-loader @babel/preset-env core-js@babel /core
{ test: /\.js$/, exclude: /node_modules/, use:[ { loader: 'babel-loader', options: { presets: [['@babel/preset-env', {// Load useBuiltIns as needed: 'usage', // Specify core-JS version corejs:{version: Targets :{Chrome: '60', Firefox: '60', IE: '9', Safari: '10', edge: '17' } } ] ], cacheDirectory:true } } ], },Copy the code
source-map
Source-map: a technique that provides a map of the source code to the code after it is built (if something goes wrong after it is built, the map can trace the source code errors)
Parameters: [the inline – | hidden – | eval -] [nosources -] [being – [module -]] source – the map
devtool: 'eval-source-map'
Copy the code
The parameters listed above can be combined arbitrarily, and each combination is different. There can be seven common combinations
With all these patterns, what’s the right combination?
Finally, the best two solutions
1: Eval-source-map (high integrity, fast)
2: eval-cheap-module-souce-map (error ignores columns but contains other information, fast)
Configure esLint code style checking
Team development, specification is essential. Personally, I think ESLint is too strict and recommend that teams write a set of ESLint rules based on their own situation.
Here is a popular JS style Airbnb portal πππ
Eslint-loader esLint needs to be imported
// webpack.config.js {test: /\.js$/, exclude: /node_modules/, // Ignore node_modules loader: 'eslint-loader', options: {fix: true, // automatic fix},}Copy the code
After importing the Loader, you also need to write the configuration in eslintConfig of package.json
// package.json "eslintConfig": {"extends": "airbnb-base", // Airbnb style specification "env": {"browser": True // Global variables can be used in the browser (window does not give an error)}}Copy the code
Optimize code packaging build speed (production environment)
oneOf
OneOf: no backward matching is performed on the loader to optimize the packaging and construction speed of the production environment
Babel cache
Babel cache: Cache the resources after Babel processing, so that the second package build only changes the content, other unchanged content out of the cache. Therefore, the construction speed is improved
// Enable Babel cache cacheDirectory:trueCopy the code
There is a problem: files with the same name are cached when the file name has not changed. The modified content may be inconsistent with the actual displayed content.
Solution: Use hash names and change file names to determine which files need to be updated.
The hash value is classified into hash, chunkhash, and contenthash. Contenthash is appropriate
Hash: A unique hash value is generated each time a wepack is packed.
Chunkhash: Hash value generated by the module. The hash values for the same module are the same
Contenthash: Generates hash values based on the contents of files to ensure the uniqueness of hash values for different files
Multi-process packaging
Thread-loader enables multi-process packaging for the subsequent loaders.
The thread-loader needs to be imported
Starting thread-Loader is expensive and is not recommended for common projects
npm i -D thread-loader
Copy the code
{loader: 'thread-loader', options: {workers: 2 // Enable 2 processes}},Copy the code
externals
Externals allows certain third-party libraries to be unpackaged
externals: {
jquery: 'jQuery'
}
Copy the code
Optimize the performance of code run (production environment)
The compressed file
-
Compressed style file
Optimize – CSS -assets-webpack-plugin needs to be introduced
npm i -D optimize-css-assets-webpack-plugin Copy the code
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin') plugins: [ new OptimizeCssAssetsWebpackPlugin(), ] Copy the code
-
Compressed HTML
The HTML-webpack-plugin needs to be introduced
The HTML-webpack-plugin automatically brings in individually packaged style files via the Link tag
npm i -D html-webpack-plugin Copy the code
const HtmlWebpackPlugin = require('html-webpack-plugin') plugins: [ new HtmlWebpackPlugin({ template: / SRC /index.html', minify: {// collapseWhitespace: true, // remove comment removeComments: true}}),]Copy the code
-
Js code is automatically compressed in production
Tree shaking
If you think of a program as a tree, the useful code or third-party library we’re using represents the green leaf. The dead code, the dead code represents the withered leaves. Tree shaking is like a big invisible hand shaking the tree down dead leaves (useless code).
Tree shaking
1: must use ES6 modularization 2: Start production environment
Under both conditions, WebPack automatically removes our useless code
You can write configuration items in package.json to control the tree swing range
// Not shaking "sideEffects": [".css", ".less"]Copy the code
The code segment
Webpack packs js code into a build.js file, which can be fatal for large projects. The build.js file is too large, resulting in long page loading times, a small change in the code to download the entire file, and many other problems.
Code splitting splits a large bundle.js file packed with output into smaller files so that multiple files can be loaded in parallel faster than loading a single file.
There are three ways to implement code splitting:
1: multi-entry split (entry entry uses multiple entry files)
entry: {
index: './src/js/index.js',
test: './src/js/test.js'
},
output: {
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
},
Copy the code
2: Configuration optimization
optimization: {
splitChunks: {
chunks: 'all'
}
},
Copy the code
3: import Dynamic import syntax
Import ('/test '). Then (({a, b}) = > {/ / file loading successful ~}). The catch (() = > {/ / file loading failure ~});Copy the code
Lazy loading
Lazy loading: files are loaded when they are needed
Preload: Load in advance before use
Lazy loading and preloading can be realized through dynamic import
// webpackPrefetch: true enables preloading import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(() => { ... });Copy the code
So much for webPack optimization. This summary may not be comprehensive, but it is sufficient for most projects. Encourage together, good good study, day day up.
Scatter flowers πΈπΈπΈπΈ disk πΈπΈ
Click like π to see again, has become a habit! This series is constantly updated, and your one-key three-link is the biggest motivation for me to continue writing. If you have any comments and suggestions on this blog, welcome to leave a message! Welcome to disturb! π π
I am Qin Aide, a programmer in the Internet to survive!