基于老项目升级webpack的心路历程
老项目,构建时长久的不敢想象,升级不敢动,一动动全身,各处报错,无从下手。结合自己的经验,一步步把架构升级的主体弄好,对于其他报错就可实际问题一个个解决,排除干扰项。
先从package解剖:
1) 升级至对应webpack版本
"webpack": "^3.6.0"
替换为:
"webpack": "^4.26.0"
"webpack-cli": "^3.3.0" (使用 webpack 4+ 版本,需要安装 CLI)
2) 查看"webpack-dev-server": "^2.9.1"源码文件中peerDependencies知依赖的webpack版本为2.x, 3.x。 所以平时在升级时要多注意包peerDependencies的依赖版本
"webpack-dev-server": "^2.9.1"
替换为:
"webpack-dev-server": "^3.11.0"
3) html-webpack-plugin同上由于依赖项缘故
"html-webpack-plugin": "^2.30.1"
替换为:
"html-webpack-plugin": "^3.2.0"
4) babel-loader同上由于依赖项缘故
"babel-loader": "^7.1.1"
替换为:
"babel-loader": "^8.1.0"
5) "babel-loader": "^8.1.0" 的依赖项为@babel/core,故需将babel周边进行升级
"babel-core": "^6.22.1"
"babel-preset-env": "^1.3.2"
"babel-plugin-transform-runtime": "^6.22.0"
替换为:
"@babel/core": "^7.4.4"
"@babel/preset-env": "^7.3.4"
"@babel/plugin-transform-runtime": "^7.11.0"
6) 从babel7.4开始,官方不推荐再使用@babel/polyfill转译
"babel-polyfill": "6.22.0"
替换为:
"@babel/runtime-corejs3": "^7.12.5"
如果对babel-polyfill、babel-preset-env、babel-plugin-transform-runtime的理解不清不楚,这里安利一个博主写的系列文章,清晰易懂
7) 升级vue-loader、eslint-loader:解决TypeError: Cannot read property 'vue' of undefined、TypeError: Cannot read property 'eslint' of undefined此类报错
"vue-loader": "^13.3.0"
"eslint-loader": "^1.7.1"
替换为: "vue-loader": "^14.2.2"
"eslint-loader": "^2.0.0"
8) 对于vue项目内支持使用JSX需安装的配套插件
"babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-helper-vue-jsx-merge-props": "^2.0.3",
官网推荐的说明有如下规则:(我在babel7环境测试使用babel-plugin-transform-vue-jsx 3.x 的版本也能支持JSX, 不知是否是其他特殊写法不支持么,如若遇到JSX问题,可按官网推荐调整下版本,如果没有的话,忽视就好≧◠◡◠≦✌):
1、如果你使用的babel版本为6.x, 相对应的转译插件为babel-plugin-transform-vue-jsx 3.x
2、如果你使用的babel插件为7.x, 那么相对应的插件应该为babel-plugin-transform-vue-jsx 4.x 或者是 @vue/babel-plugin-transform-vue-jsx
关于babel-plugin-transform-vue-jsx说明
关于@vue/babel-plugin-transform-vue-jsx说明
build文件夹下配置修改:
1) 增加mode属性: 开发模式:mode: 'development'; 生产模式:mode: 'production'
2) CommonsChunkPlugin的废除,由splitChunks替代,默认的splitChunks配置如下:
module.exports = { optimization: { splitChunks: { chunks: 'async', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } } };
当然如果需要根据自身项目合理自定义,安利博文
3) 更换提取css的插件,对mini-css-extract-plugin不了解,点击
"extract-text-webpack-plugin": "^3.0.0" 替换为: "mini-css-extract-plugin": "^0.9.0", utils.js文件: if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) }
替换为: if (options.extract) { return [MiniCssExtractPlugin.loader].concat(loaders) }
webpack.prod.conf.js文件:
new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), allChunks: false })
替换为: new MiniCssExtractPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), allChunks: false, ignoreOrder: true })
4) 关于混淆压缩 , 因为webpack4带有内置的terser-webpack-plugin,故插件uglifyjs-webpack-plugin可去掉
"uglifyjs-webpack-plugin": "^1.1.1" // 去除 new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, sourceMap: config.build.productionSourceMap, parallel: true }) 更改为: new terserPlugin({ cache: true, parallel: true, sourceMap: false })
如若对混淆压缩打包感兴趣,可参考
5)既然是优化,少不了按需加载这个概念,支持第三方组件按需加载插件
如elementUI: 借助 babel-plugin-component,只引入需要的组件,以达到减小项目体积的目的
"babel-plugin-component": "^1.0.0", // element团队在基础上修改,未提PR,自成一家,具体使用: 参考element文档说明更改
如vxe-table:借助 babel-plugin-import,引入需要的组件
"babel-plugin-import": "^1.13.1", // Ant团队最先提出, 具体使用: 参考vxe-table文档说明更改
本以为按需加载的插件下一个就行,忽然来了两个,用的不明不白,顺手查了关于两者之间区别说明
6)最后如遇到此报错:BaseClient.js?e917:12 Uncaught TypeError: Cannot assign to read only property 'exports' of object '#
去除resolve('node_modules/webpack-dev-server/client')即可正常,原因不详,暂时无深入研究。
完成上面的步骤路程走了70%,下面接着根据项目的实际情况按以下思路进行优化:
1)还是从package.json下手,对于老项目,往往会存在很多不再使用的第三方包,删除dependencies中未引用的包
2)借助webpack-bundle-analyzer工具,将如下图所示处改为true, 执行npm run build即可得到分析结果
分析项目中过大的npm包,能否替换成体积更小的包,以及如若引入了echarts等,也需配置成按需加载
3)开启多线程打包,合理利用thread-loader, cache-loader处理性能开销大的loader(这个需要根据项目来进行测试是否达到优化的目的),从而优化构建时间
如若完成上续步骤,还想继续深入,更进一步的优化方案送上
只有耐得住性子,方可拨开云雾见月明
案例Demo: vue-cli2-webpack4-youhua