文章目录
  1. 1. 软件包升级
  2. 2. CommonChunksPlugin升级
  3. 3. UglifyJSPlugin升级
  4. 4. Webpack 4 添加mode
  5. 5. Vue-Loader 升级
    1. 5.1. Vue-Loader 15 兼容性升级,需要显式导入 VueLoaderPlugin
    2. 5.2. Vue-Loader 15 兼容性升级,必须显式的指定less loader
    3. 5.3. Vue-Loader 14 兼容性升级,默认输入ES6 module,并且移除了esModule:false 支持
      1. 5.3.1. 针对Vue文件
      2. 5.3.2. 针对JS文件
      3. 5.3.3. 针对CSS文件
      4. 5.3.4. 针对图片文件
      5. 5.3.5. 针对字体文件
  6. 6. 升级后注意

软件包升级

1
2
3
4
5
6
7
8
9
10
"html-webpack-plugin": "^3.2.0",
"vue-loader": "^15.9.0",
"webpack": "^4.42.0",
"copy-webpack-plugin": "^5.1.1",
"file-loader": "^5.1.0",
"inline-manifest-webpack-plugin": "^4.0.2",
"svg-sprite-loader": "^4.2.1",
"terser-webpack-plugin": "^2.3.5",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.3"

CommonChunksPlugin升级

Webpack 4 兼容性升级,Webpack4 不再支持 CommonChunksPlugin这个插件了,使用了新的splitChunks

重要的区别是

  1. 新的配置放在了optimization下面了,不再放在plugins里
  2. 配置cacheGroups的逻辑和原来CommonChunksPlugin不完全一样,需要去理解文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
optimization: {
splitChunks: {
cacheGroups: {
uilib: {
name:'uilib',
chunks: 'initial',
test: /node_modules.\_?(mint-ui|cube-ui)/,
priority: -10,
},
vendor: {
name:'vendor',
chunks: 'initial',
test: /node_modules./,
priority: -20,
}
}
},
runtimeChunk: {
name: "manifest"
},
},

UglifyJSPlugin升级

Webpack 4 兼容性升级,Webpack4 不再支持UglifyJSPlugin,需要改为TerserPlugin

重要的区别是

  1. UglifyJSPlugin 不支持ES6了,所以用TerserPlugin
  2. TerserPlugin要放在 .optimization.minimizer 下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
config.optimization.minimizer.push(new TerserPlugin({
terserOptions: {
output: {
comments: false,
},
compress: {
collapse_vars: true,
reduce_vars: true
},
warnings: false,
},
parallel: true,
sourceMap: false,
cache: true,
}));

Webpack 4 添加mode

Webpack 4 兼容性升级,需要设置mode

正式包就用 production

1
2
3
4
5
6
7
8
9
const config = merge(baseConfig, {
name: plugin,
mode: 'production',
output: {
path: urls.moduleDistPath,
filename: "[name].[chunkhash:8].bundle.js",
chunkFilename: "[name].[chunkhash:8].bundle.js",
}
})

调试时用 development

1
this.config.mode = 'development';

Vue-Loader 升级

Vue-Loader 15 兼容性升级,需要显式导入 VueLoaderPlugin

必须在处理html之前,设置好VueLoaderPlugin去解析vue文件。https://vue-loader.vuejs.org/migrating.html#a-plugin-is-now-required

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: htmlPath,
inject: true,
chunks: ['uilib', 'vendor', 'manifest', 'app']
}),
new webpack.HashedModuleIdsPlugin(),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"windows.jQuery": "jquery"
})
],

Vue-Loader 15 兼容性升级,必须显式的指定less loader

相关文档 https://vue-loader.vuejs.org/migrating.html#loader-inference

1
2
3
4
5
6
7
8
9
10
11
12
13
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
},{
loader: "css-loader",
options: {
esModule: false,
},
}, {
loader: "less-loader" // compiles Less to CSS
}]
}

Vue-Loader 14 兼容性升级,默认输入ES6 module,并且移除了esModule:false 支持

解决方案:各个Loader需要兼容esModule

针对Vue文件

对于Vue-Loader生成的 文件,需要静态替换源代码, 所以自己编写require替换插件 compatible-es-module.js 如下:

目的是把 require(‘./xx.vue’) 替换为 require(‘./xx.vue’).default。

1
2
3
4
5
6
7
8
module.exports = function(content) {
return content.replace(
new RegExp(/require\(('|")(.*)[/\w\.]+\.vue(.*)('|")\)(\.default)?/,'g'),
function(res) {
const result = /(\.default)$/.test(res)? res: (res + '.default');
return result;
});
};

当Vue文件引用Vue文件时:

1
2
3
4
5
test: /\.vue$/,
use: [
'vue-loader',
path.resolve(path.join(urls.localNodeModulePath, 'compatible-es-module')),
]

针对JS文件

1
2
3
4
5
6
7
8
9
10
11
12
13
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015', 'stage-2'],
comments: true,
cacheDirectory: true
}
},{
loader: path.resolve(path.join(urls.localNodeModulePath, 'compatible-es-module')),
}
]

针对CSS文件

处理css esModule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
test: /\.styl$|\.stylus$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
esModule: false,
},
},
'stylus-loader'
]
}, {
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
esModule: false,
},
},
"postcss-loader"
]
},

针对图片文件

处理图片 esModule

1
2
3
4
5
6
7
8
9
10
11
12
13
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: 'images/[hash:7].[name].[ext]',
esModule: false,
}
}
]
},

针对字体文件

处理字体 esModule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
test: /\.ttf$/,
loader: 'url-loader',
options: {
//不设置大小,存为base64
name: 'font/[name].[ext]',
esModule: false,
}
}, {
test: /\.(eot|svg|woff|woff2)(\?\S*)?$/,
loader: 'file-loader',
options: {
esModule: false,
},
}]

升级后注意

webpack4 升级后。vue-loader 更改了模块导出格式。

从原来的CommonJS标准改为了ES2015 Module。ES2015 Module的关键字是import,CommonJS的关键字是require,而import 是JS语言的标准,require是社区的标准。

所以建议

  1. 尽量优先用 import。在确定要用require的时候用require。

  2. 需要require 一个vue 文件时,请务必加上后缀(为了兼容自定义的 compatible-es-module.js 插件)

    比如要require Test.vue 不要写成Vue.component(‘test’, require(‘./Test’)) 请写成 Vue.component(‘test’, require(‘./Test.vue’))

文章目录
  1. 1. 软件包升级
  2. 2. CommonChunksPlugin升级
  3. 3. UglifyJSPlugin升级
  4. 4. Webpack 4 添加mode
  5. 5. Vue-Loader 升级
    1. 5.1. Vue-Loader 15 兼容性升级,需要显式导入 VueLoaderPlugin
    2. 5.2. Vue-Loader 15 兼容性升级,必须显式的指定less loader
    3. 5.3. Vue-Loader 14 兼容性升级,默认输入ES6 module,并且移除了esModule:false 支持
      1. 5.3.1. 针对Vue文件
      2. 5.3.2. 针对JS文件
      3. 5.3.3. 针对CSS文件
      4. 5.3.4. 针对图片文件
      5. 5.3.5. 针对字体文件
  6. 6. 升级后注意