Recently, the company project has been upgraded from webpack4 to webpack5. After configuring the long-term cache of webpack5, the secondary build speed has been directly accelerated by more than 80%, and the packaging volume has also been reduced. Of course, the premise is that there are not many pits in the investigation.
There are some methods on the Internet to directly upgrade all relevant packages, but I upgrade them one by one, if necessary, upgrade again, and some packages are not upgraded (such as babel-loader, etc.), and most of the projects themselves are also newer Version.
Webpack5 new features
First of all, we must first understand what benefits can be brought to us by upgrading Webpack5, first look at the new features of Webpack5
- Improves build performance by persistent hard disk caching capabilities
- Improve long-term caching through better algorithms (reduce the cache failure rate of product resources)
- optimizes the size of the product through better Tree Shaking capabilities and code generation logic
- Improve the compatibility of the web platform
- Removed some strange state left over from the internal structure when some new features were introduced without major updates in Webpack4
- By introducing some major changes to prepare for some future features, enabling long-term stability on the Webpack5 version
The most attractive thing for me is the improvement of build performance and better tree shaking ability to optimize the size of the product.
Why has the build speed made a qualitative leap in the Webpack5 version?
Mainly because:
Webpack4 generates chunkhash based on the structure of the code. Adding blank lines or comments will cause chunkhash changes. Webpack5 generates chunkhash based on the content. Changing comments or variables will not cause chunkhash changes. Browsers can continue to use the cache.
- Optimized the use efficiency of the cache. In webpack4, chunkId and moduleId are both self-incrementing ids. As long as we add a new module, the number of modules in the code will change, which will cause the moduleId to change, and the file content will change. The same is true for chunkId. When an entry is added, the change in the number of chunks causes a change in chunkId, which leads to a change in file content. Therefore, the actual unchanged chunk files cannot be used effectively. webpack5 uses a new algorithm to calculate deterministic chunkId and moduleId. The cache can be used effectively. In production mode, optimization.chunkIds and optimization.moduleIds will be set to'deterministic' by default.
- A new configuration item that can write the cache to the disk is added. The current build task is terminated on the command line. When the build is started again, the last cache written to the hard disk can be reused to speed up the build process.
The above three explanations are quoted from . The speed of the Webpack5 build is amazing, and the early upgrade will benefit early
After a brief understanding of the above, simply record some of the things I did during the upgrade process, and check the official upgrade documentation for complete suggestions.
Upgrade dependencies directly
Some of the following libraries do not need to be compatible after our project is directly upgraded to the latest version, and there are not many configurations. However, if your project plug-in writes many configuration items, there may be places that need to be compatible.
- webpack webpack-cli
- html-webpack-plugin
- terser-webpack-plugin
- mini-css-extract-plugin
- style-loader, css-loader, postcss, postcss-loader (upgrade)
compatible
Resource module type
In webpack4 and before, we will use various loaders to process some resources, such as file-loader
, url-loader
, raw-loader
etc., but webpack5 has built-in static resource construction capabilities, and there is no need to install these additional loaders. Static can be achieved through simple configuration Packaging of resources.
Asset module type (asset module type), replace all these loaders by adding 4 new module types:
asset/resource
Send a separate file and export the URL. Previously achieved by usingfile-loader
.asset/inline
exports the data URI of a resource. Previously achieved by usingurl-loader
.asset/source
Export the source code of the resource. Previously achieved by usingraw-loader
.asset
automatically chooses between exporting a data URI and sending a separate file. Previously, it was achieved by usingurl-loader
and configuring resource volume restrictions.
example:
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
type: `asset/resource`
}
]
},
webpack-dev-server
Note that: webpack-dev-server v4.0.0+ requires node >= v12.13.0
Upgrade webpack-dev-server to ^4(next) version, otherwise HMR will be abnormal
- The startup method of
webpack-dev-server
is: 061718e90c222f. webpack5 is modified to:
webpack server
// v4 devServer: { contentBase: path.resolve(__dirname, '../dist'), compress: true, inline: true, // 在构建变化后的代码会通过代理客户端来控制网页刷新 host: '0.0.0.0', port: PORT, clientLogLevel: 'info', historyApiFallback: true, stats: 'errors-only', disableHostCheck: true, }
// v5 devServer: { // contentBase 变为 static 对象里面来配置 static: { directory: path.resolve(__dirname, '../dist'), }, client: { logging: 'info', }, compress: true, // inline: true, // 直接移除,没有替代项 host: '0.0.0.0', port: PORT, historyApiFallback: true, allowedHosts: 'all', // 代替 disableHostCheck: true // 新增中间件配置 devMiddleware: { stats: 'errors-only', }, },
related articles:
webpack-dev-server v3 migration v4 guide
Webpack5 removes Node.js Polyfill (compatible)
Webpack5 removes the Node.js Polyfill, which will cause some packages to become unavailable ('XXX' is not defined in the console). If you need to be compatible with Nodejs Polyfills such as process/buffer, you must install the relevant Polyfill: process , And explicitly declare injection in Plugin. The process variable is used in the business code, so it needs to be compatible, and the process/buffer library must be installed at the same time.
{
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser',
}),
]
}
Upgrade obsolete configuration items
The meaning of the project configuration items before changes (config/webpack_prod.ts):
splitChunks: {
chunks: 'all',
minSize: 30000, // 模块要大于30kb才会进行提取
minChunks: 1, // 最小引用次数,默认为1
maxAsyncRequests: 5, // 异步加载代码时同时进行的最大请求数不得超过5个
maxInitialRequests: 3, // 入口文件加载时最大同时请求数不得超过3个
automaticNameDelimiter: '_', // 模块文件名称前缀
name: true, // 自动生成文件名
cacheGroups: {
// 将来自node_modules的模块提取到一个公共文件中
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10, // 执行优先级,默认为0
},
// 其他不是node_modules中的模块,如果有被引用不少于2次,那么也提取出来
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true, // 如果当前代码块包含的模块已经存在,那么不在生成重复的块
},
},
},
// v5
splitChunks: {
cacheGroups: {
// vendors ——> defaultVendors
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10, // 执行优先级,默认为0
},
},
},
This can be changed in (config/webpack_prod.ts)
splitChunks.name (removed)
splitChunks.name represents the name of the extracted file
- In v4, the configuration defaults to true, which means that the file name is automatically generated
- v5 removed the name: true of optimization.splitChunks: automatic naming is no longer supported
Migration: Use the default value. chunkIds: "named" will give your file a useful name for easy debugging
output configuration (compatible)
(node:58337) [DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_HASH] DeprecationWarning: [hash] is now [fullhash] (also consider using [chunkhash] or [contenthash], see documentation for details)
Hash has been deprecated and changed to fullhash. This name is clearer than the original hash
config/webpack_dev.ts
// v4
output: {
filename: 'js/[name].[hash].js',
chunkFilename: 'js/[name].[hash].js',
},
// v5
output: {
filename: 'js/[name].[fullhash].js',
chunkFilename: 'js/[name].[fullhash].js',
},
Optimize configuration items (deprecated and removed)
(config/webpack_prod.ts)
// webpack v4, has been deprecated in v5, so it needs to be removed
new webpack.HashedModuleIdsPlugin()
HashedModuleIdsPlugin Role: to achieve persistent caching. The module ID is calculated by HashedModuleIdsPlugin, which replaces the ID based on the number increment with the hash of the module itself. In this case, the ID of a module will only change when it is renamed or removed, and the new module will not affect its ID change.
webpack5 adds support for certain moduleId and chunkId, the configuration is as follows:
optimization.moduleIds = 'deterministic'
optimization.chunkIds = 'deterministic'
This configuration is enabled by default in production mode. Its function is to assign 3-5 digits IDs to modules and chunks in a deterministic way, instead of the v4 version of HashedModuleIdsPlugin.
Global variable writing (compatible)
module.exports = () => {
return {
// ...
plugins: [
// webpack5 定义环境变量的写法变了
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
// webpack4的写法
// new webpack.DefinePlugin({
// 'process.env': {
// NODE_ENV: JSON.stringify('production'),
// },
// }),
],
};
};
Use the cache attribute to optimize the cache (new)
By default, webpack5 will not enable persistent caching. If you don’t manually add cache configuration yourself, webpack5 is not optimized. It is slower to directly upgrade the secondary build; instead of automatically speeding up the upgrade, you still have to configure it manually.
When cache.type: "filesystem" is set, webpack will enable file system caching and memory caching in a hierarchical manner internally. When reading from the cache, the memory cache will be checked first, and if the memory cache is not found, it will be downgraded to the file system cache. Write to the cache will write to the memory cache and file system cache at the same time.
The file system cache does not directly serialize requests for disk writes. It will wait until the compilation process is complete and the compiler is idle. The reason for this is that serialization and disk writing will take up resources, and we don't want to delay the compilation process.
cache: {
// 将缓存类型设置为文件系统,默认为memory
type: 'filesystem',
buildDependencies: {
// 当构建依赖的config文件(通过 require 依赖)内容发生变化时,缓存失效
config: [__filename],
// 如果你有其他的东西被构建依赖,你可以在这里添加它们
},
},
In order to prevent the cache from being too fixed, resulting in unawareness of changing the build configuration, the old cache is still used. By default, each modification of the build configuration file will cause the cache to restart. Of course, you can also actively set the version yourself to control the update of the cache.
Final optimization results
Compiling for the first time:
Second compilation:
Effect: The second construction speed is increased by more than 85%
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。