前段时间接受了一个旧项目,也不算旧 ,项目一直在做,但是没有人去做依赖升级.一直使用老版本两三年.接手后总是莫名其妙的问题出现,搞的心态都崩了,在熟悉了一段时间后,慢慢采用最保守的组件写法 . 完成此次需求.
趁着提前做完了功能, 测试bug也差不多改好了, 离发布还有一段时间,就想着拉一个新的复制版本,在本地做一次升级 . 记录一下此次依赖升级遇到的问题及解决方法.
当前该项目时vue项目,没有使用vue-cli
脚手架 . 这里采用逐步升级策略,优先主要依赖升级.
npm版本
我本地当前的npm版本:
$ npm -v
7.19.1
vue 版本升级
项目中版本为v2.5.2
, 我们升级到vue2最新版本v2.6.14
有大版本 , 保持更新是很有必要的,一些潜在的问题的修复、新特性等 .
$ npm update vue
一上来就报错了 :cry: 错误大意是当前的[email protected]
版本和组件库uxcool(公司内部的) 依赖echart@3.*
有冲突,需要解决.
好,既然有问题,那就根据提示解决这个问题 .
-
--force
强制拉取当前安装包的最新版本,不管本地已存在的副本. -
--legacy-peer-deps
npm采用安全的策略去处理各个依赖包中的不同版本.
这里涉及到npm安装依赖的规则.先不做过深的说明(:dog: 我也不懂) .
至少可以看到这与升级vue版本并没有关系,直接采用安装指定版本方式,避开更新时依赖冲突检测
$ npm install [email protected]
没有报错,package.json
中版本已为最新,项目启动也没有什么问题.
webpack 升级
项目中webpack 版本v3.6.0
, 升级到稳定版本webpack4v4.46.0
$ npm install [email protected]
存在依赖冲突, extract-text-webpack-plugin
、html-webpack-plugin
、webpack-dev-server
依赖的是webpack3 ,安装时会报错,先卸载这几个包,之后再重新安装.
$ npm remove extract-text-webpack-plugin html-webpack-plugin webpack-dev-server
不知道哪些包会影响webpack的安装,就直接install
根据错误提示,剔除影响的依赖包.
安装成功后,依次安装之前写在的依赖.
webpack-dev-server 升级
当前版本为v2.9.1
,升级到最新为v3.11.2
$ npm install webpack-dev-server --save-dev
启动npm run dev
无法启动,需要安装webpack-cli
和webpack
配合使用.
webpack-cli
提供了一些开发中常用的默认配置以及命令.
$ npm install --save-dev webpack-cli
重新启动时,报错 , 说是找不到模块webpack-cli/bin/config-yargs
然后开始找解决方案, 最后查到是由于
webpack-cli
版本更新的问题, 也在github 的issue 里看到这个问题的解决方案.
- 可以降低版本,我安装的是
v4.7.2
可以降低到v3 - 启动命令不再是
webpack-dev-server
, 采用webpack serve
我才用了第二种,修改package.json
{
"scripts": {
- "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+ "dev": "webpack serve --inline --progress --config build/webpack.dev.conf.js",
},
}
好了,启动没有报错了.
extract-text-webpack-plugin 升级
这个依赖的作用用于将多个文件中的内容提取到一个单独的文件中.
在这个项目中,它的作用用于分离组件中的css,将多个组件中的css样式打包成一个文件,从而减少静态资源的请求数量.
因为要升级到webpack4 , 官方建议使用mini-css-extract-plugin
那就修改webpack部分配置.卸载它,安装 mini-css-extract-plugin
,最新版本为v2.1.0
安装时报错,需要webpackv5.0.0
所以指定版本 v1.6.2
$ npm install --save-dev [email protected]
肯定是有一些优点的 , 只有在生产环境下处理CSS的拆分:
- 异步加载
- 更易使用
- 不会重复编译
- 只处理CSS
修改配置文件,全局搜索使用了该组件的地方,进行修改:
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
// ...
plugins: [
- new ExtractTextPlugin({
- filename: utils.assetsPath('css/[name].css?v=' + utils.staticVersion()),
- }),
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].css?v=' + utils.staticVersion()),
chunkFilename: 'css/[id].css',
}),
]
}
处理loader
配置, extract-text-webpack-plugin 配置loader
// 工具类处理多个环境下的规则定义 util.js
// ... 省略其他代码
if (options.extract) {
- return ExtractTextPlugin.extract({
- use: loaders,
- fallback: 'vue-style-loader'
- })
+ return [MiniCssExtractPlugin.loader].concat(loaders)
} else {
return ['vue-style-loader'].concat(loaders)
}
html-webpack-plugin 升级
当前项目中版本为v2.30.1
升级到webpack4的版本v4.5.2
$ npm i --save-dev html-webpack-plugin@4
部分需要调整的配置 , 用于生产编译时的配置:
module.exports = {
plugins: [
new HtmlWebpackPlugin({
// ...
minify: { //
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
- chunksSortMode: 'dependency',
+ chunksSortMode: 'auto', // 可选值更改为 none auto manual
}),
]
}
废弃的webpack plugin
-
webpack.NamedModulesPlugin()
标识模块,方便调试 -
new webpack.NoEmitOnErrorsPlugin()
有错误时 , 不会生成错误的包. -
new webpack.optimize.ModuleConcatenationPlugin()
预编译模块 - 生产配置
现在改用配置项:
module.exports = {
optimization: {
noEmitOnErrors: true,
namedModules: true,
concatenateModules:true,
}
}
vue-loader 升级
处理完webpack相关的依赖项之后,启动项目,正常编译. 进度到最后报错
当前项目版本为v13.3.0
, 升级到v14.2.4
$ npm install --save-dev [email protected]
重新启动,启动成功,
babel 升级
包括babel-loader \ babel-core \ babel-preset-env
, 移除旧的依赖包
安装新的依赖包:
babel-loader
@babel/core
@babel/preset-env
# remove
$ npm remove babel-loader babel-core babel-preset-env
# add
$ npm install babel-loader @babel/core @babel/preset-env --save-dev
安装完成之后,修改webpack.base.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
- loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')],
+ use:{
+ loader:'babel-loader',
+ options:{
+ presets:[
+ ['@babel/preset-env', { targets: "defaults" }]
+ ]
+ }
+ }
},
]
}
}
启动后报错 , 我们已经卸载了babel-preset-env
安装了@babel/preset-env. 但
babel-loader` 的依赖并没有读取到了.
.babelrc
配置修改
需要修改.babelrc
文件 如下, 解决之前的问题.
{
"presets": [
- ["env", {
+ ["@babel/preset-env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}
重新启动后, 报错
这让我意识到babel相关的组件都有可能重新以@babel
为前缀命名,挨个查了下相关的组件,进行全部升级
@babel/plugin-syntax-jsx
@babel/plugin-transform-runtime
@babel/preset-stage-2
# remove
$ npm remove babel-plugin-syntax-jsx babel-plugin-transform-runtime babel-preset-stage-2
# add
$ npm install @babel/plugin-syntax-jsx @babel/plugin-transform-runtime @babel/preset-stage-2 --save-dev
修改.babelrc
{
"presets": [
["@babel/preset-env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
- "stage-2"
"@babel/preset-stage-2"
],
- "plugins": ["transform-vue-jsx", "transform-runtime"]
+ "plugins": [
"transform-vue-jsx",
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-jsx"
]
}
启动时发现@babel/preset-stage-2
设置已不同,根据提示
@babel/preset-stage-2
配置调整
和之前版本不同的是 , 最新的babel
把所有的预设都废弃了, 需要自行安装
$ npm install @babel/plugin-proposal-decorators @babel/plugin-proposal-function-sent @babel/plugin-proposal-export-namespace-from @babel/plugin-proposal-numeric-separator @babel/plugin-proposal-throw-expressions --save-dev
重新修改.babelrc
, 具体都是根据官方文档增加配置的
{
"presets": [
["@babel/preset-env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
- "stage-2"
- "@babel/preset-stage-2"
],
- "plugins": ["transform-vue-jsx", "transform-runtime"]
+ "plugins": [
"transform-vue-jsx",
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-jsx",
["@babel/plugin-proposal-decorators", { "legacy": true }],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions"
]
}
启动后没有报错.
babel-plugin-transform-vue-jsx
升级
项目当前版本为v3.7.0
, babel 7 需要升级到v4.0.1
$ npm install [email protected] --save-dev
升级这个是因为编译后,测试部署后 ,报错h undefined
, 就想到可能没解析JSX语法。
项目编译
测试完升级的各项功能都比较正常,暂时没有发现问题, 测试编译:
CommonsChunkPlugin
webpack4 中已经移除, 使用splitChunksPlugin
代替. 用于拆分公共模块,便于缓存加载,从而提升页面加载速度.
错误提示的也很明显, 根据官网文档,重新配置下
SplitChunksPlugin
有默认配置行为, 提升页面加载性能.
- 共享的模块来自于
node_modules
文件夹 - 拆分的包大于30kb,没压缩之前
- 按需加载的并行请求数低于或等于5
- 初始页面加载时的最大并行请求书低于或等于3
module.exports = {
optimization:{
splitChunks:{
chunks: 'async', // 定义哪一类模块被优化 all async initial
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
}
}
}
}
}
vue-style-loader
和style-loader
作用相似 , 在引入mini-css-extract-plugin
后,编译配置项 ,不在需要vue-style-loader
如果在编译时引入了vue-style-loader
则会报错
// ...
if (options.extract) {
return [MiniCssExtractPlugin.loader,'vue-style-loader'].concat(loaders)
} else {
return ['vue-style-loader'].concat(loaders)
}
官网示例也说明了这点 ,
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
],
},
plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};
配置 Eslint、husky
为了规范大家的代码格式、git提交格式,配置Eslint以及husky .
Eslint 安装
之前配置过一个项目 , 所以这一块回忆一下很快就处理好了.
# 安装
$ npm install eslint --save-dev
# 初始化配置文件
$ npx eslint --init
执行第二个命令后,会出现交互窗口,让你选择适合你项目的一些选择项. 最后安装需要的依赖
eslint-plugin-vue
eslint-config-standard
eslint-plugin-import
eslint-plugin-node
eslint-plugin-promise
安装完成之后,自动生成配置文件.eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'plugin:vue/essential',
'standard'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
plugins: [
'vue'
],
rules: {
}
}
修改package.json
增加脚本 ,设置检测src/
目录下的所有文件, 并进行自动修复.
{
"scripts": {
"lint":"npx eslint src/ --fix"
},
}
先执行测试npx eslint src/
发现了2974个错误 , 加上参数后--fix
只剩下41 个错误了.
husky 安装
配置了eslint 还不够, 出现错误可以不修复直接提交, 安装husky后可以在commit 之前先lint ,不通过则不允许提交.
配置安装:
$ npm install husky --save-dev
安装完成之后需要初始化一次
# 会在package.json 生成一个脚本
$ npm set-script prepare "husky install"
# 执行该脚本
$ npm run prepare
执行完成之后,可以看到项目目录下生成.husky/
文件夹 , 初始化成功.
创建commit 钩子
$ npx husky add .husky/pre-commit "npm run lint"
# 添加到git hook 中
$ git add .husky/pre-commit
会在.husky/
目录下生成pre-commit
文件, 可以打开进行编辑.
现在可以测试提交下刚才未处理的41条错误的文件了, 发现提交不了 , 处理完错误后,就可以提交成功了 :yum:
有一个问题就每次都会检测src
下的所有文件, 就会很麻烦, 实际中我们只希望校验自己更改过的文件.
安装依赖lint-staged
:
$ npm install --save-dev lint-staged
创建配置文件lint-staged.config.js
/**
* git 提交文件校验
* 暂存区文件格式校验
*/
module.exports = {
"src/**/*.{js,ts,vue,tsx,jsx}": "eslint --fix",
};
可以在package.json
新增一个脚本
{
"scripts": {
"lint-staged": "npx lint-staged --config lint-staged.config.js",
},
}
调整.husky/pre-commit
执行的命令
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
- npm run lint
+ npm run lint-staged
commitlint 配置
配置好代码格式校验 , 大家可以愉快的提交代码了. 另一个问题就是commit message 的格式 .
使用@commitlint/cli
对我们的 commit message 信息进行格式校验.
安装依赖 , 使用别人共享出来的规范angular
比较普遍吧 @commitlint/config-angular
:
$ npm install --save-dev @commitlint/cli @commitlint/config-angular
生成git hook:
$ npx husky add .husky/commit-msg "npm run commitlint"
定义package.json
脚本
{
"scripts": {
"commitlint": "npx commitlint -e",
},
}
创建配置文件进行配置commitlint.config.js
/**
* git push
* 提交信息规范校验
*/
module.exports = {
extends:['@commitlint/config-angular'],
rules:{
"type-enum":[
2,
"always",
["feat","fix","docs","style","refactor","test","chore"]
]
}
}
修改一下脚本, 指向该配置文件
npx commitlint -e --config commitlint.config.js
基本的重要依赖升级就都完成了,剩下的都是业务组件相关依赖,需要评估是否可以升级,会涉及到修改代码,就暂时不做升级。