前言
自从vue-cli推出了3.0版本之后就一直在研究使用,手头的新项目都上了3.0,2.0的老项目也切了几个。
相较于2.0版本Webpack配置一大堆,3.0封装了绝大部分的Webpack相关配置并暴露了一些可配置的参数接口(比如vue.config.js文件)。
3.0上手确实容易多了✈️
封装之后上手是简单了,但是自定义也更加困难了。
需求
老项目有两个需求,分页
和分包缩减
。
分页
“分页”是业务上的需求,因为项目有两大业务类别,所以需要分包实现。参照官网的pages配置即可。
module.exports = {
pages: {
index: {
// page 的入口
entry: 'src/index/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: 'Index Page',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index']
},
// 当使用只有入口的字符串格式时,
// 模板会被推导为 `public/subpage.html`
// 并且如果找不到的话,就回退到 `public/index.html`。
// 输出文件名会被推导为 `subpage.html`。
subpage: 'src/subpage/main.js'
}
}
分包缩减
这个由用户反馈而来。因为项目中了用了一些UI库(通过WebpackBundleAnalyzer观察得),打包后的vendors包特别大,1M多,gzip后也有3、400k大小,直接影响首屏的加载,可以考虑的方法是将UI库分包。
看了下Vue-cli 3的文档,没有相关分包加载的直接设置项,但是可以自定义Webpack的配置。
chainWebpack——结合webpack-chain的链式操作API,直接修改项目Webpack配置。
configureWebpack——将定义的配置对象merge到Webpack配置中。
chainWebpack
直接操作Webpack配置,比如加入包分析工具WebpackBundleAnalyzer、设置alias等等。
const WebpackBundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const isAnalyze = true; // 是否启用bundleAnalyzer
// ...
module.defaults = {
// ...
chainWebpack: config => {
config.resolve.alias // 设置alias
.set('Less', resolve('src/less'));
if (isAnalyze) { // 设置bundle-analyzer
config
.plugin('bundle-analyzer')
.use(WebpackBundleAnalyzer);
}
// ...
},
// ...
}
configureWebpack
可以设置optimization.splitChunks.cacheGroups
配置分包。
// 以拆element-ui为例
module.exports = {
// ...
configureWebpack: {
optimization: {
splitChunks: {
cacheGroups: {
theme: {
name: 'chunk-theme',
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
chunks: 'all',
priority: 1,
reuseExistingChunk: true,
enforce: true
}
}
}
}
},
// ...
}
分包实现
SPA
如果是SPA,只需要通过vue-cli 3的默认配置和上面的configureWebpack
配置即可实现。
Sample配置如文末仓库。
MPA
如果是MPA,就没那么简单了。由于每个入口只需要自己的js和公共chunks、UI-chunk,所以默认的pages配置已经不能满足需求了(html-webpack-plugin的一些参数vue-cli3并不支持配置,需要自己修改webpack配置实现)。
所以这边的解决方案是:
- configureWebpack的内容不变,依然是ui分包的配置;
- 不使用vue.config.js中的
pages
,在chainWebpack
中自行加入entry
和HtmlWebpackPlugin
;
具体实现就不写了,Sample配置见文末仓库。
注意点
在实现的时候遇到了一些问题,这边记录一下。
1. TypeError: Cannot read property 'tapAsync' of undefined
google后得到结果是”html-webpack-plugin”不能放在”preload-webpack-plugin”的后面。link
配置chainWebpack时添加html-webpack-plugin时使用.before('xxx')
方法即可。
2. 配置了分页后,dev环境不能访问每个分页怎么办
webpack-dev-server有一个参数配置historyApiFallback
,可以实现dev模式下的分页访问。
3. index.html中的BASE_URL未定义
默认情况下,vue-cli会给process.env
注入几个属性值,其中就有BASE_URL
,值为'/'
。
但是当进行MPA配置时是我们自写的插件配置,所以必须要将BASE_URL
写入到htmlWebpackPlugin的templateParameters
中。(即使vue.config.js中配置了baseUrl)