将公司旧webpack3升级到5,踩坑总结
前言
由于手上目前负责公司的项目属于相对老旧的项目,每次打包构建的时候都要等近两分钟。这让我这个急性子实在无法接受。然后打算去优化一下。看了一下webpack版本是3。目前最新都是5了。据说打包时间会有一定提升。最主要的还是可以支持一些新插件和特性。我便着手进行webpack大版本的升级。这注定是一此项目地震。
先看成果
[23:20:42] Finished 'build' after 1.28 min
[23:20:42] Starting 'create:versionCatalog'...
......
[23:20:42] Starting '<anonymous>'...
[23:20:42] Finished '<anonymous>' after 36 ms
[23:20:42] Finished 'default' after 1.3 min
只看build这个过程一共花费了1.28分钟。 看看升级之后的的效果。
[21:59:37] Finished 'build' after 43 s
[21:59:37] Starting 'create:versionCatalog'...
[21:59:37] Finished 'create:versionCatalog' after 263 ms
......
[21:59:37] Starting '<anonymous>'...
[21:59:37] Finished '<anonymous>' after 31 ms
[21:59:37] Finished 'default' after 44 s
build这个过程之花了43秒,速度上面是有一定提升的。
升级过程以及关键点
具体升级细节我就不多描述了。可以参考这两篇文章。我就简单截取一些关键点。
依赖调整
一般教程推荐使用npm-check-updates进行其他适配版本的升级,但是我为了让记忆深刻点。我选择一个个发现进行升级。期间调整的依赖有以下几个。若有读者问题可以进行补充。
包名 | 处理方式 | 新版本号 |
---|---|---|
webpack | 升级 | 5.37.0 |
webpack-dev-server | 升级 | ^4.7.4 |
webpack-cli | 升级 | ^4.9.2 |
webpack-merge | 升级 | ^5.8.0 |
html-webpack-plugin | 升级 | ^5.3.2 |
copy-webpack-plugin-cli | 升级 | ^10.2.4 |
css-loader | 升级 | ^6.7.1 |
svg-sprite-loader | 升级 | ^6.0.11 |
friendly-errors-webpack-plugin | 升级 | ^1.7.0 |
postcss-loader | 升级 | ^6.2.1 |
vue-loader | 升级 | ^15.9.8 |
url-loader | 删除 | - |
file-loader | 删除 | - |
vue-style-loader | 删除 | - |
style-loader | 新增 | ^3.3.1 |
extract-text-webpack-plugin | 删除 | |
mini-css-extract-plugin | 新增 | ^2.6.0 |
optimize-css-assets-webpack-plugin | 删除 | |
css-minimizer-webpack-plugin | 新增 | ^3.4.1 |
plugins及一些依赖使用方式的改变
这里我只记录有哪些公共点需要调整。具体怎么调整再以上推荐文章里有提,不多做赘述。读者可以根据列出来的几点去以上文章里找对应具体修改。
- 项目webpack-dev-server升到了4版本用来配套webpack5,所以npm run dev的命令需要相改为webpack serve启动
- 需要再plugins里面增加VueLoaderPlugin(vue-loader)
- extract-text-webpack-plugin和optimize-css-assets-webpack-plugin已经过时了需要由mini-css-extract-plugin和css-minimizer-webpack-plugin来代替
- webpack5自带了资源解析,所以不需要什么url-loader,file-loader之类的,直接用assets就可以解析
- 调整copyWebpackPlugin(copy-webpack-plugin)使用方法
- webpack-merge要解构出来,const { merge } = require('webpack-merge')
- NamedModulesPlugin已过时,由optimization的moduleIds进行替换
- copy-webpack-plugin插件使用方式有变化
- devServer改动很多可以参考以上文章链接,自定义参考官网devserver专题
- UglifyJsPlugin已经过时,可以直接使用webpack5开箱提供的TerserPlugin
- 代码拆分webpack.optimize.CommonsChunkPlugin已经过时现在使用webpack5提供的optimization.splitChunks属性来实现功能来实现
- build->util.js文件中修改了一处 MiniCssExtractPlugin.loader。ExtractTextPlugin(extract-text-webpack-plugin)已过时,使用MiniCssExtractPlugin(mini-css-extract-plugin)进行替换。
- devtool有做一定修改
- 由于vue-loader升级了,所以之前css如果使用/deep/有可能出错。我是在根节点使用/deep/然后换到::v-deep就正常了。如果有类似问题,可以相应调整。
以下几点我有做自己的调整。
- TerserPlugin进行代码压缩的时候,去除了注释。对应官网
new TerserPlugin({
terserOptions: {
format: {
comments: false,
},
},
extractComments: false
})
去掉了vue-style-loader使用style-loader替代。原因css-loader从V4版本开始默认开启esModule,导致css无法被vue-style-loader解析的问题,解决方案有两个我选择替换替换vue-style-loader。具体: github.com/vuejs/vue-l…
- MiniCssExtractPlugin我调整了一下css生成位置和名字。
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].css'),
chunkFilename: utils.assetsPath('css/[id].[contenthash].css')
}),
对应的utils.js里面的MiniCssExtractPlugin中的publicPath也要相应修改。
return [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../../'
}
}].concat(loaders)
- splitChunks调整。我为了将所有css合并为一个css所以调整了一下cacheGroups
splitChunks: {
···
cacheGroups: {
vendors: {
name: 'vendors',
test({ resource }) {
return /[\/]node_modules[\/]/.test(resource);
},
priority: -10
},
styles: {
name: "styles",
chunks: "all",
type: "css/mini-extract",
enforce: true,
priority: 10,
}
}
}
由于该项目使用glup构建工具,所以也有一定调整。调整我也列出来。
- 由于去掉了manifest.js文件。所以对应处理replace:cdnUrl的流程也就去掉。相对应解决动态cdn的方法改为使用webpack内部变量__webpack_public_path__进行调整。具体方法。可以参考进行替代。
- 由于使用TerserPlugin所以代码混淆会有差异。所以要调整replace:version过程替换版本号的匹配目标。 旧的:
gulp.task('replace:version', function () {
return gulp.src(`${versionPath}/static/config/index-${env}.js`)
.pipe($.replace(/window.SITE_CONFIG['version'] = '.*'/g, `window.SITE_CONFIG['version'] = '${version}'`))
.pipe(gulp.dest(`${versionPath}/static/config/`))
});
新的:
// 替换${versionPath}/static/config/index-${env}.js window.SITE_CONFIG['version']配置变量
gulp.task('replace:version', function () {
return gulp.src(`${versionPath}/static/config/index-${env}.js`)
.pipe($.replace(/window.SITE_CONFIG.version=".*"/g, `window.SITE_CONFIG['version'] = '${version}'`))
.pipe(gulp.dest(`${versionPath}/static/config/`))
});
全部的gulpfile.js配置我列一下。
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var path = require('path');
var del = require('del');
var distPath = path.resolve('./dist');
var version = ''; // 版本号
var versionPath = ''; // 版本号路径
var env = ''; // 运行环境
// 创建版本号(年月日时分)
(function () {
var d = new Date();
var yy = d.getFullYear().toString().slice(2);
var MM = d.getMonth() + 1 >= 10 ? (d.getMonth() + 1) : '0' + (d.getMonth() + 1);
var DD = d.getDate() >= 10 ? d.getDate() : '0' + d.getDate();
var h = d.getHours() >= 10 ? d.getHours() : '0' + d.getHours();
var mm = d.getMinutes() >= 10 ? d.getMinutes() : '0' + d.getMinutes();
version = yy + MM + DD + h + mm;
versionPath = distPath + '/' + version;
})();
// 编译
gulp.task('build', $.shell.task([ 'node build/build.js' ]));
// 创建版本号目录
gulp.task('create:versionCatalog', function () {
return gulp.src(`${distPath}/static/**/*`)
.pipe(gulp.dest(`${versionPath}/static/`))
});
// 替换${versionPath}/static/config/index-${env}.js window.SITE_CONFIG['version']配置变量
gulp.task('replace:version', function () {
return gulp.src(`${versionPath}/static/config/index-${env}.js`)
.pipe($.replace(/window.SITE_CONFIG.version=".*",/g, `window.SITE_CONFIG['version'] = '${version}',`))
.pipe(gulp.dest(`${versionPath}/static/config/`))
});
// 合并${versionPath}/static/config/[index-${env}, init].js 至 ${distPath}/config/index.js
gulp.task('concat:config', gulp.series(function () {
return gulp.src([`${versionPath}/static/config/index-${env}.js`, `${versionPath}/static/config/init.js`])
.pipe($.concat('index.js'))
.pipe(gulp.dest(`${distPath}/config/`))
}));
// 清空
gulp.task('clean', function () {
return del([versionPath])
});
gulp.task('getEnv', function (cb) {
// 获取环境配置
env = process.env.NODE_ENV || 'prod'
cb()
})
gulp.task('default', gulp.series('clean', 'getEnv', 'build', 'create:versionCatalog', 'replace:version', 'concat:config', function () {
// 清除, 编译 / 处理项目中产生的文件
return del([`${distPath}/static`, `${versionPath}/static/config`])
}));
总结
那么一套升级流程下来过程还算有收获。我将我的一些踩坑点记录在里面。前人踩坑填坑,后人走平路。希望读者有收获的话可以点下赞和收藏哦。
下一步将进行webpack打包后大小的调整。因为我发现打包之后的js文件反而变大了。 希望读者期待笔者的webpack5优化篇。
听说点赞会加薪、升职、变帅、变美欸亲
转载自:https://juejin.cn/post/7083146700939853832