记录一次两年前的Vue项目升级

前段时间接受了一个旧项目,也不算旧 ,项目一直在做,但是没有人去做依赖升级.一直使用老版本两三年.接手后总是莫名其妙的问题出现,搞的心态都崩了,在熟悉了一段时间后,慢慢采用最保守的组件写法 . 完成此次需求.

趁着提前做完了功能, 测试bug也差不多改好了, 离发布还有一段时间,就想着拉一个新的复制版本,在本地做一次升级 . 记录一下此次依赖升级遇到的问题及解决方法.

当前该项目时vue项目,没有使用vue-cli 脚手架 . 这里采用逐步升级策略,优先主要依赖升级.

npm版本

我本地当前的npm版本:

$ npm -v
7.19.1

vue 版本升级

项目中版本为v2.5.2 , 我们升级到vue2最新版本v2.6.14

有大版本 , 保持更新是很有必要的,一些潜在的问题的修复、新特性等 .

$ npm update vue

一上来就报错了 :cry: 错误大意是当前的echarts@4.9.0 版本和组件库uxcool(公司内部的) 依赖echart@3.* 有冲突,需要解决.

好,既然有问题,那就根据提示解决这个问题 .

image-20210802113100591.png
  • --force 强制拉取当前安装包的最新版本,不管本地已存在的副本.
  • --legacy-peer-deps npm采用安全的策略去处理各个依赖包中的不同版本.

这里涉及到npm安装依赖的规则.先不做过深的说明(:dog: 我也不懂) .

至少可以看到这与升级vue版本并没有关系,直接采用安装指定版本方式,避开更新时依赖冲突检测

$ npm install vue@2.6.14

没有报错,package.json 中版本已为最新,项目启动也没有什么问题.

webpack 升级

项目中webpack 版本v3.6.0 , 升级到稳定版本webpack4v4.46.0

$ npm install webpack@4.46.0

存在依赖冲突, extract-text-webpack-pluginhtml-webpack-pluginwebpack-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-cliwebpack配合使用.

webpack-cli提供了一些开发中常用的默认配置以及命令.

$ npm install --save-dev webpack-cli

重新启动时,报错 , 说是找不到模块webpack-cli/bin/config-yargs

image-20210802154646741.png

然后开始找解决方案, 最后查到是由于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 mini-css-extract-plugin@1.6.2

肯定是有一些优点的 , 只有在生产环境下处理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相关的依赖项之后,启动项目,正常编译. 进度到最后报错

image-20210802170104282.png

当前项目版本为v13.3.0 , 升级到v14.2.4

$ npm install --save-dev vue-loader@14.2.4

重新启动,启动成功,

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` 的依赖并没有读取到了.

image-20210802193144015.png
.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"]
}

重新启动后, 报错

image-20210802194235781.png

这让我意识到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 babel-plugin-transform-vue-jsx@4.0.1 --save-dev

升级这个是因为编译后,测试部署后 ,报错h undefined , 就想到可能没解析JSX语法。

项目编译

测试完升级的各项功能都比较正常,暂时没有发现问题, 测试编译:

CommonsChunkPlugin

webpack4 中已经移除, 使用splitChunksPlugin 代替. 用于拆分公共模块,便于缓存加载,从而提升页面加载速度.

image-20210803092627898.png

错误提示的也很明显, 根据官网文档,重新配置下

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)
  }
image-20210803171704291.png

官网示例也说明了这点 ,

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:

image-20210803175323985.png

有一个问题就每次都会检测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

基本的重要依赖升级就都完成了,剩下的都是业务组件相关依赖,需要评估是否可以升级,会涉及到修改代码,就暂时不做升级。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容