感觉是突然之间,webpack4的消息就满天飞了,听说打包速度提高了很多,还有最大的噱头是实现了零配置,leader有一天就吩咐我说,有时间把我们的项目也升个级呗。好嘞。
1.x到2.x
这次升级跨度比较大,我们是从webpack1.x升级到4.x,因为1.x与2.x相差挺大,所以第一件事,就是先升到2.x,比较大的改动就是loader
的配置方式
// 1.x
preLoaders: [
{
test: /\.vue$/,
loader: 'eslint',
exclude: /node_modules/
}, {
test: /\.js$/,
loader: 'eslint',
exclude: /node_modules/
}
],
loaders: [
{ test: /\.vue$/, loader: 'vue' },
{ test: /\.json$/, loader: 'json' },
{ test: /\.html$/, loader: 'html' },
...
]
//2.x
module: {
rules: [
{
test: /.vue$/,
use: 'eslint-loader',
enforce: 'pre', // 对应1.x的preLoaders
exclude: /node_modules/
}, {
test: /.js$/,
use: 'eslint-loader',
enforce: 'pre',
exclude: /node_modules/
},
{ test: /\.vue$/, use: 'vue-loader' },
{ test: /\.json$/, use: 'json-loader' },
{ test: /\.html$/, use: 'html-loader' },
...
]
},
而且loader
一定要写完整,vue-loader
如果只写vue
会报错。loader
还可以通过options
进行配置。
{
loader: 'css-loader',
options: {
autoprefixer: false
}
}
旧版的链式调用也用数组替代。
1.x
style!postcss!less
2.x
use: [
"style-loader",
"css-loader",
"less-loader"
]
webpack2.x
默认支持es6的模块,所以在编译时候没有必要将它们先转换CommonJS
模块再处理,babel-preset-es2015-webpack
已经支持不转换模块中的import
和export
,只需要设置.babelrc
"presets": [
["es2015", { "modules": false }]
]
另外就是插件的升级,运行时哪个插件报错就升级哪个插件,屡试不爽。
2.x到4.x
第一步:版本升级
- 不再支持
node 4
,可以直接升级到8.x版本 -
webpack
升级
npm install webpack@4 --save
npm install webpack-cli --save // 不要忘记这一点,用来启动webpack的
- 插件升级,同理,哪个报错就升级哪个,除了
html-webpack-plugin
用下面的方法升级,原因是作者还未来得及升级
npm i webpack-contrib/html-webpack-plugin --save-dev
extract-text-webpack-plugin
只有最新的beta版本才支持,所以npm install extract-text-webpack-plugin@next --save-dev
第二步 运行命令中添加 --mode development
和--mode production
PS:虽然说webpack 4
是零配置,入口默认是src/index.js
,出口是dist/
,但由于项目是多页面的,所以这一步并没有省略,根据实际情况来。
第三步 移除CommonsChunkPlugin
//替代方案
module: {
rules: [
...
]
},
optimization: {
splitChunks: {
chunks: "all", // 必须三选一:'initial' | 'all' | 'async'
minSize: 0,
minChunks: 1,
maxAsyncRequests: 1,
maxInitialRequests: 1,
name: () => {},
cacheGroups: {
vendor: {
chunks: 'all',
test: /node_modules/, // 正则规则验证,如果符合就提取chunks
name: "vendor" // 要缓存的分割出来的chunk名称
},
default: {
chunks: 'all',
name: 'commons',
reuseExistingChunks: true
}
}
}
}
因为多个页面,所以结合了html-webpack-plugin
new HtmlWebpackPlugin({
template: 'index.html',
chunks: ['vendor', 'commons', 'index']
})
刚开始一直出错,是因为我没有复写default
,也没有default:false
,所以其实默认配置有将所有的模块的公共部分分离到某个文件中,但我在HtmlWebpackPlugin
中的chunks
中又没有添加,所以要么覆写原来的默认配置,要么就关闭默认配置。
第四步:配置postcss autoprefixer
在根目录下创建一个文件`postcss.config.js`
module.exports = {
plugins: [
require('postcss-inline-svg')({
removeFill: false
}),
require('postcss-pxtorem')({
replace: process.env.NODE_ENV === 'production',
rootValue: 750 / 16,
minPixelValue: 1.1,
propWhiteList: [],
unitPrecision: 5
}),
require('autoprefixer')({browsers: ['iOS>7', 'Android>4']})
]
};
...
{
test: /\.(css|less)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use:[{
loader: 'css-loader',
options: {
autoprefixer: false
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true
}
},
{
loader: 'less-loader',
options: {
relativeUrls: true
}
}]
})
},
...
第五步:不需要UglifyJsPlugin插件
只需要设置optimization.minimize: true
就行,production mode
下面自动为true
以上只是在原有项目的基础上对webpack 4
的升级,还有一些特性并没有用到,所以没有提及,比如sideEffects
、javascript/auto javascript/esm javascript/dynamic
、webassembly/experimental
等等,有机会再去探索。