directory
- Webpack5 new features
- Summary of problems upgrading to webpack5
- Start optimizing terms
- To optimize
- Use the new cache attributes to optimize the cache
- Resolve partial optimization
- Module partial optimization
- Optimization of
- The plugin part
- Multithreaded packaging
- Other optimizations
- The final result
1. New webPack5 features
- Increased persistent storage capability to improve build performance (core)
- Improve algorithmic capabilities to improve long-term caching (reduce cache failure rates for production resources)
- Improved Tree Shaking reduces product size and code generation logic
- Improve web platform compatibility
- Cleaned up some weird states in the internal architecture that were left over when Webpack4 introduced some new features without a major update
- Long term stability in Webpack5 releases by introducing some significant changes to prepare for future features
2. Upgrade to WebPack5
Fault 1: The format of the env environment object is changed
Cause: In Webpack4, –env.xx XXX is used to pass environment variables to the webpack.config file. In Webpack5, the following error is reported
–env. Xx XXX –env xx= XXX
Error 2: Webpack-dev-server Cannot find module ‘webpack-cli/bin/config-yargs
Solution: Change webpack-dev-server to Webpack serve, or change webpack-CLI version to 3.x
Question 3: Using babel-loader? CacheDirectory error
Solution:
- Use the cache added in Webpack5
- Use Happypack to pack the cache
Problem 4: Unusablehard-source-webpack-plugin
The plug-in
When using plug-ins, TypeError is reported: Cannot read property ‘tap’ of undefined solution: Webpack5 deprecated the hard-source-webpack-plugin and can use webpack’s new cache properties instead
Question 5:Conflicting values for 'process.env.NODE_ENV'
An error
Error using new webpack.defineplugin to define NODE_ENV
Question 6:Can't resolve '.. /.. /core-js/object/define-property
An error
Solution: Add a rule to the module.
module: {
rules: [{
test: /\.m? js/.// fix:issue: https://github.com/webpack/webpack/issues/11467
resolve: {
fullySpecified: false,},... ] }},Copy the code
Question 7:merge is not a function
An error
Const {merge} = require(‘webpack-merge’) const merge = require(‘webpack-merge’)
3. Start optimizing items
- Webpack, as a mainstream front-end packaging tool, has complex configuration items. Just taking over optimization, I don’t know where to start:
It can be optimized from the following ideas:
Idea 1:
First determine which modules can be optimized. Webpack main configurations (Entry, Output, Resolve, module, Performance, externals, module, plugins, and others) can be optimized
Idea 2:
Use the package volume detection tool Webpack-bundle-Analyzer to analyze the package size and start optimizing
Idea 3:
Use packaging speed and each module detection plug-in speed-measure-webpack-plugin to analyze and optimize
4. Start optimizing
Use the newcache
Attributes, cache optimization (recommended)
-
Prior to Webpackage 5, you would use cache-loader to write compiled structures to the disk cache, or use babel-loader? CacheDirectory =true sets Babel compilation to be written to disk cache.
-
The cache attribute added in webpack5 will enable disk caching by default, and the compilation result will be cached in node_modules/. Cache /webpack by default.
-
When cache.type: “filesystem” is set, webpack internally enables filesystem caching and memory caching in a hierarchical manner. When reading from the cache, the memory cache is first looked at, and if it is not found, it is demoted to the file system cache. The write cache writes to both the memory cache and the file system cache.
-
The file system cache does not serialize requests to disk directly. It will not execute until the compilation process is complete and the compiler is idle. The reason for this is that serialization and disk writes take up resources, and we don’t want to delay the compilation process any further.
Resolve part optimization:
externals
(recommended): Public CDN reference is performed for third-party packages to reduce the package size
Module.exports = {// add the react/jquery CDN address to index.html and set the external CDN reference to module.exports = {... externals: { react: 'React', jquery: 'jQuery' } ... };Copy the code
resolve.alias
: Uses aliases to shorten reference module paths and reduce file parsing costs. (Webpack uses enhanced-resolve to resolve the file path. If the file path is relative, the file path will be spliced first, and then the module reference. Alias will not splice the file path, and the cache will be directly after the reference:Webpack.docschina.org/concepts/mo…)
Module.exports = {resolve: {alias: {'@': path.resolve(' SRC '), // @ : path.resolve(' SRC '),}}Copy the code
resolve.mainFields
: Reduces third-party module search steps.webpack.target
The default isbrowserslist
andweb
whentarget
forweb
orwebworker
When the value is["browser", "module", "main"]
, which can lead to unnecessary searches. Because most third-party modules are usedmain
Field to describe the location of the entry file, which can be set directly to:
Module.exports = {resolve: {mainFields: ['main'],},}; // exports = {resolve: {mainFields: ['main'],},};Copy the code
- The reasonable configuration
resolve.extensions
Retrieve file type- Keep the list values to a minimum
- High frequency file types are suffixed first
- Import statements in source code as far as possible write file suffixes, such as
require(./data)
To be writtenrequire(./data.json)
module.exports = {
...
resolve:{
extensions: ['.js', '.jsx'],
}
}
Copy the code
Module partial optimization
include
andexclude
: exclude the loader file from processing.cache-loader
(recommended): Caches the parsed files of the Loader. By default, the files are saved innode_modueles/.cache/cache-loader
Under directory (andcache
Combined use reduces speed by about 10%.
rules: [
{
test: /.ext$/,
use: ['cache-loader', ...loaders],
include: path.resolve('src'),
},
],
Copy the code
- Set up the
noPrase
(Not recommended)And:external
Similar, but cannot coexist. The main function module skips compilation, and the difference lies in whether it needs to extract to CDN for asynchronous loading
module.exports = {
module:{ noParse:[/jquery|chartjs/, /react.min.js$/] }
}
Copy the code
Optimization of
- Get rid of
uglifyjs-webpack-plugin
To switch toterser-webpack-plugin
Do code compression (uglifyjs-webpack-plugin
The community has lost maintenance, are 2 years ago code, although also support multi-process, but the measured effect is obviously not as good asterser-webpack-plugin
)
module.exports = {
...
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
...
};
Copy the code
optimize-css-assets-webpack-plugin
(recommended): Compresses CSS
module.exports = {
...
optimization: {
minimize: true,
minimizer: [
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.css$/,
safe: true,
cache: true,
parallel: true,
discardComments: {
removeAll: true,
},
}),
],
},
...
};
Copy the code
splitChunks
The code segment(recommended): Main function is to extract common code, prevent code from being repeatedly packaged, split large JS files, merge scattered JS files)
module.exports = {
...
optimization: {...splitChunks: {
chunks: "all".// Specify whether to pack synchronously or asynchronously
minSize: 30000.// The chunk will be partitioned only when the chunk is larger than 30,000
minRemainingSize: 0.maxSize: 0.// Attempts to split code based on this size
minChunks: 1.// Specify how many times to split the code
maxAsyncRequests: 6.maxInitialRequests: 4.automaticNameDelimiter: "~".// File generated concatenator
cacheGroups: {
defaultVendors: { test: /[\\/]node_modules[\\/]/.// Meet the requirements of the group to build venders
priority: -10.// Priority is used to determine which package to go into
filename: "vendors".// Specify the chunks name},
default: {
minChunks: 2.// Select * from *
priority: -20.reuseExistingChunk: true.// Check if it has been referenced before,}}}... }Copy the code
RuntimeChunk: Creates an additional file or chunk to reduce the size of entry Chunk and improve performance.
module.exports = {
```
optimization: {
runtimeChunk: true
}
}
Copy the code
The Plugin part
- Eslint-webpack-plugin: Alternative to eslint-loader, which can be configured with auto-fix and multi-core compilation
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
// ...
plugins: [new ESLintPlugin()],
// ...
};
Copy the code
mini-css-extract-plugin
(recommended): Removes the CSS file for uploading the CDN- DllPlugin (Not recommended): mainly used for caching. Recommended by webpack5
cache
(Extract the base module that the web page depends on and package it into a DLL file. When the module to be imported exists in a DLL, the module is no longer packaged, but obtained from the DLL.) - Hardsourcewebpackplugin (webpack5 error, recommend to use cache instead) : Issue: github.com/mzgoddard/h…
Multithreaded packaging
-
Using Happypack: When packaging a build, Happypack creates a thread pool that splits the build task module and allocates threads to each module and its dependencies. After the processing is complete, there is a communication process that transfers the processed resources to one of the main processes of HappyPack to complete the entire build process.
- Method of use:
-
Id: The ID associated with loader set in the configuration file will be set to the instance first for one-to-one matching between Loader and Plugin
-
Name: indicates that the plug-in type is HappyPack, which helps you quickly locate the corresponding plugin in loader and avoids the risk of errors caused by id attributes in other plug-ins
-
const happyThreadPool = HappyPack.ThreadPool({ size: 3 });
module: {
rules: [{
test: /\.js[x]?$/,
use: [ 'happypack/loader?id=jsx']
}]
}
plugins: [
new HappyPack({
id: 'jsx',
threadPool: happyThreadPool,
loaders: [
{
loader: 'babel-loader',
},
verbose: true,
],
...
}),
Copy the code
- Use thread – loader
- Note: Thread-loader cannot be used in conjunction with the Mini-CSS-extract-plugin
- How it works: Similar to HappyPack, each time webPack parses a module, Thread-Loader assigns it and its dependencies to worker processes
- Use:
Include: path.resolve(' SRC '), // include: path.resolve(' SRC '), // include: path.resolve(' SRC '), // [ 'babel-loader', { loader: 'thread-loader', options: { workers: 3, }, }, // 'happypack/loader', ] } ]Copy the code
Other optimizations
- use
mode
attribute - Js-tree-shaking: package.json set side-effect: false, remove dead code
- Tips: Third-party packages can also be optimized, such as LoDash. By using
import { throttle } from 'lodash-es'
Instead ofimport { throttle } from 'lodash'
(lodash-es willLodash Library exported asES Module, support tree shaking based on ES Modules
- Tips: Third-party packages can also be optimized, such as LoDash. By using
purgecss-webpack-plugin
: Take CSS files tree-shaking(Recommended, CSS files may be significantly reduced)- The Module Federation: webpack5 new micro front-end solutions, public NPM, and post consumer component code (example: webpack.docschina.org/concepts/mo…
- Esbuild-loader: faster than babel-loader
5. Final results
- Packing speed before optimization:
- Packing volume before optimization:
- Optimized packing speed:
- Optimized packing volume: