记一次 vue2.6 工程改造升级

386 阅读4分钟

首先介绍一下背景,我是19年初来公司,当时采用了最新的 vue-cli3 来作为工程脚手架,开放了vue-config.js 进行了一些简单的配置就开始了开发 时光飞逝,今年已经是第4个年头,公司还是使用的当年的技术,由于之前业务需求多,时间紧迫,所以就一直沿用了当时的技术到今天,尽管项目初期就采用了git submodule 的方式对基础组建,进行了封装,但是由于工程浩大,代码量已经数十万行,编译编译时间较长,且团队成员还在使用较为落后的技术,亟须进行技术改造升级,引入新技术,势在必行。

准备工作

  1. 切换node 版本
nvm use 20
  1. 替换 yarn.lock 中失效的镜像源地址 最新地址 registry.npmmirror.com
  2. 升级 chromedriver 升级到 129.0.4

1. 升级 vue-cli

npm remove vue-cli -g
npm add vue-cli -g

2. 执行 vue upgrade

vue upgrade
包名当前版本升级后版本
@typescript-eslint/eslint-plugin^2.18.0^5.4.0
@typescript-eslint/parser^2.18.0^5.4.0
@vue/cli-plugin-babel~4.2.0~5.0.8
@vue/cli-plugin-e2e-nightwatch~4.2.0~5.0.8
@vue/cli-plugin-eslint~4.2.0~5.0.8
@vue/cli-plugin-pwa~4.2.0~5.0.8
@vue/cli-plugin-router~4.2.0~5.0.8
@vue/cli-plugin-typescript~4.2.0~5.0.8
@vue/cli-plugin-unit-mocha~4.2.0~5.0.8
@vue/cli-plugin-vuex~4.2.0~5.0.8
@vue/cli-service~4.2.0~5.0.8
@vue/eslint-config-standard^5.1.0^6.1.0
@vue/eslint-config-typescript^5.0.1^9.1.0
eslint^6.7.2^7.32.0
eslint-plugin-import^2.20.1^2.25.3
eslint-plugin-node^11.0.0^11.1.0
eslint-plugin-promise^4.2.1^5.1.0
eslint-plugin-vue^6.1.2^8.0.3
typescript: ~3.7.5~4.5.5

3. 升级 core-js

yarn remove core-js
yarn add core-js
包名当前版本升级后版本
core-js^3.6.4^3.30.0

4. 向后兼容

// 视情况而定
// vue.config.js
configureWebpack: (config) => {
  config.resolve.fallback = {
    path: require.resolve('path-browserify'),
    os: require.resolve('os-browserify/browser'),
    crypto: require.resolve('crypto-browserify'),
    stream: require.resolve('stream-browserify')
  }
}
// 视情况而定
yarn add path-browserify os-browserify crypto-browserify stream-browserify


5. vue-config.js 配置项变更

  // vue-config.js
  {
    css: {
      loaderOptions: {
        postcss: {
          postcssOptions: { // 原来不要这一级
            plugins: [
              require('postcss-pxtorem')({
                rootValue: 10,
                propList: ['*'], // 可以将 px 转换为 rem 的属性
                selectorBlackList: [
                  /^html$/, // 如果是 regexp,它将检查选择器是否匹配 regexp,这里表示 html 标签不会被转换
                  '.px-', // 如果是字符串,它将检查选择器是否包含字符串,这里表示 .px- 开头的都不会转换
                  'el-time-'
                ], // px 不会被转换为 rem 的 选择器
                minPixelValue: 2 // 设置要替换的最小像素值(2px会被转rem)。 默认 0
              })
            ]
          }
        }
      }
    }
  }

6. 修复 & 禁止 eslint typescript 报错

  根据报错选择将对应规则关闭 or 修复对应的 eslint 报错


7. 升级 vue 版本及其相关依赖

  • 由于vue2.x 与 vue3.x 不兼容,故而采用 vue 次新版本 vue2.7,既可以使用 vue3 的新语法,又可以保留原来 vue2 的旧写法
yarn remove vue
yarn add vue@^2.7.14

yarn remove element-ui
yarn add element-ui@^2.15.13

yarn remove vue-router
yarn add vue-router@^3.6.5
包名当前版本升级后版本
vue^2.6.11^2.7.14
element-ui^2.4.5^2.15.13
vue-router^3.1.5^3.6.5

8. 打包优化尝试

开始之前可以先安装两个小工具
speed-measure-webpack-plugin // 分析耗时的地方在哪里
webpack-bundle-analyzer // 分析拆包是否合理

  1. 增加 cache-loader(旧版本自带,新版本得自己装)
configureWebpack: config => { config.module.rules.forEach((rule, index) => {
    if (rule.test.test('.vue') || rule.test.test('.ts') || rule.test.test('.tsx')) {
    rule.use.unshift('cache-loader')
    }
}
  1. 增加 fork-ts-checker 使用内存,cpu核数

    // vue.config.js
    chainWebpack: config => {
        config
          .plugin('fork-ts-checker')
          .tap(args => {
            const totalmem = Math.floor(os.totalmem() / 1024 / 1024) // get OS mem size
            const allowUseMem = totalmem > 4096 ? 4096 : 1000
            const opts = {
              memoryLimit: allowUseMem,
              workers: 4
            }
            Object.assign(args[0], opts)
    
            return args
          })
      }
    
  2. 增加 thread-loader 启动多核打包

configureWebpack: config => {
    config.module.rules.forEach((rule, index) => {
      if (rule.test.test('.vue') || rule.test.test('.ts') || rule.test.test('.tsx')) {
        rule.use[rule.use.length - 1].options.happyPackMode = true

        rule.use.splice(rule.use.length - 1, 0, {
          loader: 'thread-loader',
          // loaders with equal options will share worker pools
          options: {
            // the number of spawned workers, defaults to (number of cpus - 1) or
            // fallback to 1 when require('os').cpus() is undefined
            workers: 2,

            // number of jobs a worker processes in parallel
            // defaults to 20
            workerParallelJobs: 50,

            // additional node.js arguments
            workerNodeArgs: ['--max-old-space-size=2048'],

            // Allow to respawn a dead worker pool
            // respawning slows down the entire compilation
            // and should be set to false for development
            poolRespawn: false,

            // timeout for killing the worker processes when idle
            // defaults to 500 (ms)
            // can be set to Infinity for watching builds to keep workers alive
            poolTimeout: process.env.NODE_ENV === 'production' ? 2000 : Infinity,

            // number of jobs the poll distributes to the workers
            // defaults to 200
            // decrease of less efficient but more fair distribution
            poolParallelJobs: 50,

            // name of the pool
            // can be used to create different pools with elsewise identical options
            name: 'my-pool' + index
          }
        })
      }
    })
  1. 若不用支持ie11, 则可以使用避免二次执行 vue-cli-service build 生成 bundle
vue-cli-service build --no-module

经测试除使用1, 4能显著提高打包编译时间以外,剩下的手段貌似效果都不明显 ╮(╯▽╰)╭

9. node-sass vs dart-sass

懂得都懂,node-sass 经常 GG,体验极度不好,而且官网也推荐了使用 dart-sass 代替 node-sass, 替换后亲测安装时间的确能够减少, 分 3 步骤走,话不多说直接上教程。

  1. 安装 dart sdk
  2. 去掉node-sass, 安装 sass
yarn remove node-sass
yarn add sass
  1. 全局替换 /deep/ to ::v-deep(部分警告可有时间慢慢解决)

10. es-lint error 错误

error  Parsing error: Cannot read properties of undefined (reading 'map')

设置 vue.config.js, 临时解决 lintOnSave: false

11. path, process等在浏览器端无法使用

安装 node-polyfill-webpack-plugin,安装官方文档配置即可

结论

经过以上工程配置,项目初步运行起来了,但是优化之后的打包速度依然不是特别理想,这次先记录到这里,我会持续将优化进行下去,如果有人有更好的结果,也可以反馈给我。


thanks for watching (ง •̀_•́)ง