我负责的一个前端项目之前用到的是webpack1,现需要升级到webpack4,特此记录下升级过程中有一些配置和需要注意的问题,具体会介绍:
(1) 需要的node环境的升级
(2) mode参数切换开发模式还是生产模式
(3) 移除了CommonsChunkPlugin,改用了optimization属性进行更加灵活的配置
(4) 用新的CSS文件提取插件mini-css-extract-plugin,替换extract-text-webpack-plugin
由于篇幅较长,分为上下两篇介绍,本文主要介绍后面两点,关于前面两点的介绍,请移步升级你的webpack(上)-- webpack入门教程(二)
webpack需要使用hash来做静态资源的更新,文件名的hash值目前有三种计算hash的方式:[hash]、[chunkhash]以及[contenthash]。
区别:
[hash]:每次webpack在编译的过程中会生成唯一的hash值,项目中任何一个文件改动后就会被重新创建,然后webpack会计算新的hash值。简单来说,hash是跟整个项目的构建相关,每一次构建就生成一个hash值,即使文件内容没有改变。
[chunkhash]:根据模块计算出来的hash值,所以某个文件的改动只会影响自己的hush值,而不会影响到其他文件的hash值。
[contenthash]:由文件内容产生的hash值,内容不同产生的contenthash值就不一样。
如果项目中是把所有的内容都打包成同一个文件,那么[hash]就足够了。而如果项目中涉及到拆包、分模块进行加载等,那么需要用到[chunkhash],来保证每次更新后,只有改变的相关文件的hash值发生改变。
module.exports = {
entry: {
index: [
path.resolve(__dirname, './modules/index.js')
]
},
output: {
path: path.resolve(__dirname, '../../app/public/v2'),
filename: 'js/[name].[chunkhash:8].js',
}
}
上述代码的意思是:以index.js为入口文件,将所有的代码全部打包到一个文件名为index.xxxx.js,并放到app/public/v2/js目录下,这样每次更新代码时会生成新的命名文件了。
但这样只能应付简单的场景,在大型多页面应用中,往往需要对页面进行优化,涉及拆包、分模块加载:
(1)分离业务代码和第三方的代码:之所以将业务代码和第三方代码分离出来,是因为业务代码更新频率高,而第三方代码更新迭代速度慢,所以我们将第三方代码(库,框架)进行抽离,这样可以充分利用浏览器的缓存来加载第三方库。
(2)按需加载:比如在使用 react-router 的时候,当用户需要访问到某个路由的时候再去加载对应的组件,那么用户没有必要在一开始的时候就将所有的路由组件下载到本地。
(3)在多页面应用中,我们往往可以将公共模块进行抽离,比如 header, footer 等等,这样页面在进行跳转的时候这些公共模块因为存在于缓存里,就可以直接进行加载了,而不是再进行网络请求了。
那么如何进行拆包,分模块进行加载呢?
在webpack4之前,可以使用webpack 内置插件:CommonsChunkPlugin。从webpack4开始,optimization
替代了CommonsChunkPlugin插件,改用optimization属性进行更加灵活的配置。
每个配置项的作用:
-- minSize
分离前的最小块文件大小,单位为字节
-- minChunks
分离前该块被引入的次数
-- maxInitialRequests
一个入口文件可以并行加载的最大文件数量
-- maxAsyncRequests
内层文件(第二层)按需加载时最大的并行加载数量
-- name
用以控制分离后代码块的命名,若不存在则为 [来源]~[入口的key值].js 的格式
-- automaticNameDelimiter
修改上文中的 “~” , 若改为: “-” 则分离后的js默认命名规则为 [来源]-[入口的key值].js
-- test
用来控制哪些模块被缓存组选择,test: /node_modules/ 即为匹配相应文件夹下的模块
-- cacheGroups
缓存组,其实就是存放分离代码块的规则的对象。如果不希望使用默认配置,可以通过splitChunks.cacheGroups进行配置,cacheGroup中priority 为分离规则的优先级,优先级越高,则优先匹配。
-- chunks
匹配的块的类型:initial(初始块),async(按需加载的异步块),all(所有块)
-- priority
这个配置很重要,即便是所有配置项都写好了,优先级不够,或者优先级设置不正确,也得不到相应的结果。当需要优先匹配缓存组的规则时,priority需要设置为正数,当需要优先匹配默认设置时,缓存组需设置为负数,0为两者的分界点。
更多的配置项可参看webpack官方文档,以下是optimize.splitChunks 中的一些配置参考:
module.exports = {
optimization: {
runtimeChunk: {
name: 'manifest'
},
//webpack4不再需要UglifyJsPlugin,设定optimization.minimizer为true即可
//production mode下面自动为true
minimizer: true,
splitChunks: {
chunks: 'async',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
name: false,
cacheGroups: {
vendor: {
name: 'vendor',
chunks: 'initial',
priority: -10,
reuseExistingChunk: false,
test: /node_modules\/(.*)\.js/
},
//将多个css chunk合并成一个css文件
styles: {
name: 'styles',
test: /\.(scss|css)$/,
chunks: 'all',
minChunks: 1,
reuseExistingChunk: true,
enforce: true
}
}
}
}
}
说明:
(1) CommonsChunkPlugin需要通过配置两次new webpack.optimize.CommonsChunkPlugin来分别获取vendor和manifest的通用chunk方式已经做了整合, 直接在optimization中配置splitChunks和runtimeChunk即可 ,提取功能也更为强大。
(2) runtimeChunk可以配置成true、single或者对象,用于自动计算当前构建的一些基础chunk信息,类似之前版本中的manifest信息获取方式。
(3) webpack.optimize.UglifyJsPlugin现在不需要了,只需要使用optimization.minimizer为true即可,production mode下面自动为true,当然如果想使用第三方的压缩插件也可以在optimization.minimizer的数组列表中进行配置,例如这样配置:
//在optimization.minimizer的数字列表中配置,使用第三方的压缩插件
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
config.optimization = {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {
autoprefixer: { disable: true },
discardComments: {
removeAll: true,
},
canPrint: true
}
})
],
};
优点:
没有重复编译,性能比原来要好
异步加载,当js文件被异步加载时,需要的css文件也会自动加载
因为只针对css文件,所以自动带了一些优化,比如在mode:production时,自动minify
webpack1使用extract-text-webpack-plugin,基本配置如下:
//webpack1用extract-text-webpack-plugin:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
loaders: [
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
},
]
},
plugins: [
new ExtractTextPlugin("css/[name].[chunkhash].css"),
]
}
webpack4使用mini-css-extract-plugin,基本配置如下:
//webpack4用mini-css-extract-plugin:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'less-loader'
]
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash].css"
}),
]
}
本文详细介绍了项目中从webpack1升级到webpack4时一些需要注意的配置,如有问题,欢迎指正。
以下是webpack系列的往期文章:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。