It's not easy to refuse to pay a compliment
preface
In essence, webpack is a static module packaging tool for modern JavaScript applications. When webpack processes an application, it will internally build a dependency graph from one or more entry points, and then combine each module required in your project into one or more bundles, which are static resources for displaying your content.
Main concepts
- Entry
- Output
- loader
- Plug in
- Mode
1. Basic use
1.1 split configuration and merge
Initialize package json
npm init -y
1.1. 1. Install webpack
yarn add -D webpack webpack-cli
1.1. 2. Install webpack merge
yarn add -D webpack-merge
1.1. 3. Create a new build folder and configuration file
- build\webpack.common.js
- build\webpack.dev.js
- build\webpack.prod.js
webpack.common.js
Public configuration
const path = require('path') module.exports ={ entry:path.join(__dirname, '..', 'src/index') }
webpack.dev.js
When developing
const webpackCommon = require('./webpack.common.js') const { merge } = require('webpack-merge') module.exports = merge(webpackCommon, { mode: 'development' })
webpack.prod.js
When packing
const path = require('path') const webpack = require('webpack') const webpackCommon = require('./webpack.common.js') const { merge } = require('webpack-merge') const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = merge(webpackCommon, { mode: 'production', output: { filename: '[name].[contenthash:8].js', path: path.join(__dirname, '..', 'dist'), }, plugins: [new CleanWebpackPlugin()] })
1.1.4 Scripts
"scripts": { // Local service "dev": "webpack-dev-server --config build/webpack.dev.js", "build": "webpack --config build/webpack.prod.js" },
1.1. 5 test
New src/index
Execute yarn build
1.2 start local service
1.2. 1. Install webpack dev server
yarn add -D webpack-dev-server
1.2. 2. Configure devServer
webpack.dev.js
devServer: { port: 8080, progress: true, // Show packaged progress bar contentBase:path.join(__dirname, '..', 'dist'), // root directory open: true, // Open browser automatically compress: true, // Start gzip compression // Set agent proxy: { } }
1.2. 3 start
yarn dev
1.2. 4 test
Install HtmlWebpackPlugin to automatically generate html
yarn add -D html-webpack-plugin
Configure HtmlWebpackPlugin
webpack.common.js
plugins:[ new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/index.html'), filename: 'index.html' }) ]
The development environment will generate an html file in memory
In the packaging environment, an html file will be generated under dist
The html file is automatically imported into main js
1.3 processing ES6 (configuration babel)
13.1. install
babel-loader
yarn add -D babel-loader
@babel/core
yarn add -D @babel/core
@babel/preset-env
yarn add -D @babel/preset-env
1.3. 2. Configuration
.babelrc
{ "presets": ["@babel/preset-env"], "plugins": [] }
build\webpack.common.js
module: { rules: [ { test: /\.js$/, // Loader: 'Babel loader', / / loader is a single loader, and use is an array of loaders use: [ 'babel-loader', ], include: path.join(__dirname, '..', 'src'), exclude: /node_modules/ } ] },
1.4 handling css
1.4. 1 installation
style-loader
css is inserted into the style tag of the page
yarn add -D style-loader
css-loader
yarn add -D css-loader
postcss-loader + autoprefixer
Auto prefix
yarn add -D postcss-loader autoprefixer
1.4. 2 configuration
build\webpack.common.js
{ test: /\.css$/, // The order of loader execution is from back to front use: ['style-loader', 'css-loader', 'postcss-loader'] },
postcss.config.js
module.exports = { plugins: [require('autoprefixer')] }
1.5 processing pictures
1.5. 1 there are three ways to introduce pictures into general documents:
js file through import imgSrc from '/ photo’; img.src = imgSrc introduced
It is introduced as a background image in the css file
Import directly in html file
1.5. 2 installation
file-loader
yarn add -D file-loader
url-loader
yarn add -D url-loader
1.5. 3 configuration
build-base-conf\webpack.dev.js
// Directly import image url { test: /\.(png|jpg|jpeg|gif)$/, use: 'file-loader' }
build-base-conf\webpack.prod.js
// Picture - consider base64 encoding { test: /\.(png|jpg|jpeg|gif)$/, use: { loader: 'url-loader', options: { // Pictures less than 5kb are output in base64 format // Otherwise, the form of file loader is still used to produce url format limit: 5 * 1024, // Package to img directory outputPath: '/img1/', // Set the cdn address of the picture (it can also be set uniformly in the external output, which will act on all static resources) // publicPath: 'http://cdn.abc.com' } } },
2 advanced features
2.1 configure multiple entrances
2.1. 1. Configure entry
entry: { index: path.join(srcPath, 'index.js'), other: path.join(srcPath, 'other.js') },
index and other here are the names of chunk
2.1. 2. Configure the corresponding outlet
build-base-conf\webpack.prod.js
output: { filename: 'bundle.[contentHash:8].js', // When packaging code, add hash stamp path: distPath, // publicPath: 'http://cdn.abc.com '/ / modify the prefix of all static file URLs (such as CDN domain name), which is temporarily unavailable here },
Note that you only need to add configuration in prod here,
dev does not need
2.1. 3. Configure the corresponding template
new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/index.html'), filename: 'index.html', // Chunks indicates which chunks (i.e. index and other above) are to be referenced on the page. All chunks are referenced by default chunks: ['index'] // Only index. Is referenced js }), // Multi entry - generate other html new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/other.html'), filename: 'other.html', chunks: ['other'] // Reference only other js })
2.2 removing CSS (packaging)
2.2. 1 installation
mini-css-extract-plugin
yarn add -D mini-css-extract-plugin
2.2. 2 configuration
build\webpack.prod.js
loader
// Pull off css { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, // Note that style loader is no longer used here 'css-loader', 'postcss-loader' ] },
plugins
new MiniCssExtractPlugin({ filename: 'css/main.[contenthash:8].css' })
2.3 compressing css (packaging)
2.3. 1 installation
optimize-css-assets-webpack-plugin
yarn add optimize-css-assets-webpack-plugin
2.3. 2 configuration
build-min-extract-css\webpack.prod.js
optimization: { // Compress css minimizer: [ new OptimizeCSSAssetsPlugin({})], }
2.4 extracting public codes
Extract public code
When developing projects with multiple pages, we sometimes reference some public modules in several pages. These public modules are downloaded many times, which will cause a waste of resources. If these public modules are extracted and downloaded only once, they can be cached, so as to avoid wasting resources due to repeated downloading, So how to extract the public part from the webpack? The method is as follows:
2.4. 1 common module extraction
give an example:
The project includes A.js, B.js and page1 js, page2. JS these four JS files,
page1.js and Page2 JS also refers to A.js and B.js,
At this time, I want to separate A.js and B.js and merge them into a public JS, and then automatically introduce this public JS into page1 and Page2,
splitChunks: { cacheGroups: { //Common module extraction common: { chunks: 'initial', minSize: 0, //Greater than 0 bytes minChunks: 2 //The minimum number of times this code block is referenced when pulling away public code } } }
2.4. 2. Third party module extraction
Third party modules are sometimes introduced into the page, such as import $from 'jquery'; You need references in page1 and page2. In this case, you can use vendor to extract jquery as follows:
optimization: { // Split code block splitChunks: { chunks: 'all', /** * initial The entry chunk does not process files imported asynchronously async Asynchronous chunk, which only processes files imported asynchronously all All chunk s */ // Cache grouping cacheGroups: { // Third party module vendor: { name: 'vendor', // chunk name priority: 1, // Higher authority, priority withdrawal, important!!! test: /node_modules/, minSize: 0, // Size limit minChunks: 1 // How many times at least }, // Common module common: { name: 'common', // chunk name priority: 0, // priority minSize: 0, // Size limit of common module minChunks: 2 // How many times has the common module been reused at least } } } }
Note: you need to configure the weight priority here, because the first common configuration will be executed when pulling away. When you see that jquery is also public at the entrance, it will be pulled away together, and the wendor configuration will not be executed again. Therefore, after adding the weight, the third-party module will be pulled away first, and then the public common will be pulled away, so that the third-party and public will be pulled away.
3 performance optimization
3.1 optimize Babal loader (reduce construction objectives)
3.1. 1 reason
The file conversion operation of Loader is very time-consuming, so it is necessary to let as few files as possible be processed by Loader
3.1. 2 configuration
{ test: /\.js$/, use: [ 'babel-loader?cacheDirectory',//Enable conversion result cache ], include: path.resolve(__dirname, 'src'),//Babel loader is only used for files in src directory exclude: path.resolve(__dirname,' ./node_modules'),//Exclude node_ Files in the modules directory },
3.2 happyPack multi process packaging
3.2. 1 installation
yarn add -D happypack
3.2. 2 configuration
Plugins
new HappyPack({ // Using a unique ID to represent the current HappyPack is used to process a specific type of file, which corresponds to the use in rules id: "babel", loaders: ["babel-loader?cacheDirectory"], //The default setting is loader processing threads: 5, //Use shared pool processing }), new HappyPack({ id: 'styles', loaders: ['css-loader', 'postcss-loader'], threads: 5, //Represents opening several sub processes to process this type of file verbose: true //Allow output of days }),
rules
{ test: /\.(js|jsx)$/, use: [MiniCssExtractPlugin.loader, "HappyPack/loader?id=babel"], exclude: path.resolve(__dirname, " ./node_modules"), }, { test: /\.css$/, use: 'happypack/loader?id=styles', include: path.join(__dirname, '..', 'src') },
3.3 ParallelUglifyPlugin optimized compression
By default, webpack provides UglifyJS plug-in to compress JS code, but it uses single thread compression code, that is, multiple JS files need to be compressed, and it needs to compress files one by one.
Therefore, the speed of packaging compressed code in the formal environment is very slow (because compressing JS code requires parsing the code into an AST syntax tree abstracted by Object, and then applying various rules to analyze and process AST, resulting in a very time-consuming process).
3.3. 1 installation
yarn add -D webpack-parallel-uglify-plugin
3.3. 2 configuration
new ParallelUglifyPlugin({ // The parameters passed to UglifyJS are as follows: uglifyJS: { output: { /* Whether to output readable code, that is, spaces and tabs will be retained. The default is output. In order to achieve better compression effect, Can be set to false */ beautify: false, /* Whether to keep the comments in the code. It is reserved by default. In order to achieve better compression effect, it can be set to false */ comments: false }, compress: { /* Whether to delete all console statements in the code. The default is not to delete. When enabled, all console statements will be deleted */ drop_console: true, /* Whether to embed variables that have been defined but only used once, such as var x = 1; y = x, converted to y = 5, default to not Conversion. In order to achieve better compression effect, it can be set to false */ collapse_vars: true, /* Whether to extract static values that occur multiple times but are not defined as variables to reference, such as x = 'xxx'; y = 'xxx' converted to var a = 'xxxx'; x = a; y = a; The default is no conversion. In order to achieve better compression effect, it can be set to false */ reduce_vars: true } } } )
3.4 automatic refresh
With the help of automatic means, when the local source code file is monitored to change, the running code is automatically reconstructed, and then the browser refresh is controlled. Webpack These functions are built-in, and a variety of schemes are provided for us to choose from.
3.4. 1. Configuration of automatic refresh in the project:
module.export = { watch: true, watchOptions: { // Files or folders not listening ignored: /node_modules/, // After listening to the change, it will wait for 300ms to execute the action to prevent the file from being updated too fast, resulting in too high recompilation frequency aggregateTimeout: 300, // Judging whether the file has changed is realized by constantly asking the system whether the specified file has changed poll: 1000 } }
3.4. 2 Principle
- The principle of monitoring a file change in Webpack is to obtain the last editing time of the file regularly (which can be set in watchOptions.poll), and save the latest last editing time each time. If it is found that the currently obtained and last saved last editing time are inconsistent, the file is considered to have changed
- When a file is found to have changed, it will not immediately tell the listener, but cache it first, collect the changes for a period of time (which can be set in watchOptions.aggregateTimeout), and then tell the listener at one time. Prevent high-frequency input text that may cause file changes during code editing
3.5 module hot update
_ _ DevServer also supports a method called module hot replacement (Hot Module Replacement) technology can achieve super sensitive real-time preview without refreshing the whole web page. The principle is that when a source code changes, you only need to recompile the changed module, and then use the new output module to replace the corresponding old module in the browser. Module hot replacement technology improves the development efficiency and experience to a great extent.
Configuration of module hot replacement in the project:
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin'); devServer:{ host:'localhost', port:'8080', open:true//Automatically pull up the browser // Only hot is set, and only cssHMR takes effect hot:true,//Thermal loading //hotOnly:true }, plugins:[ //Hot update plug-in new webpack.HotModuleReplacementPlugin() ] HotModuleReplacementPlugin Generate a mainifest(One json The structure describes the change modules (list) and update file(One js (the file contains the modified code content)
JS file
if (module.hot) { module.hot.accept('./print.js', function() { //Tell webpack to accept the hot replacement module console.log('Accepting the updated printMe module!'); printMe(); }) } // Effective for Js
3.6 performance analysis
3.6.1 webpack-bundle-analyzer
]
// config/webpack.common.js const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const commonConfig = { // ... plugins: [ new BundleAnalyzerPlugin({ analyzerPort: 8889, // Specify the port number openAnalyzer: false, }), ] // ... }
3.6.2 speed-measure-webpack-plugin
// config/webpack.common.js const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); // ... module.exports = (production) => { if (production) { const endProdConfig = merge(commonConfig, prodConfig); return smp.wrap(endProdConfig); } else { const endDevConfig = merge(commonConfig, devConfig); return smp.wrap(endDevConfig); } };
Postscript
2020-10-10 webpack 5.0.0 has been released, but that doesn't mean it's complete, bug free, or even fully functional. Like webpack 4
Similarly, we continue development by fixing problems and adding new features. There may be many bug fixes in the coming days. New features may also appear.
Try using persistent caching to improve build performance. Try to improve long-term caching with better algorithms and defaults. Try to improve the package size with better Tree Shaking and code generation.
Try to improve compatibility with network platforms. Try to clean up internal structures that are in a strange state when implementing v4 functions without introducing any destructive changes.
This paper attempts to prepare for future functions by introducing breakthrough changes now, so that it can be maintained on the v5 version for as long as possible. Migration guide