vue-cli 老项目 vite 迁移记录

8,167 阅读20分钟

本文作者:卡猫司机

公司的项目大部分都是 2B 类型的中后台 PC 端项目,且业务都非常庞大。常年累月的维护下,使用webpack dev速度变得非常慢。

因为最近的工作主要是负责一些前端的基础设施建设,各个业务线的产品都有一定的接触。有一个项目在我的电脑上面npm run dev居然要 6 分钟之久,实在是难以感到愉悦。加上公司内部已经新项目使用 vite 作为构建工具,所以挑选了一个自己比较熟悉的老项目(vue-cli)进行 vite 迁移。并将过程进行了记录。

项目背景

先简单说明一下项目的情况:

  • 内容:2B 的 PC 端中后台管理系统,是一个双入口的应用(登录页一个入口,管理系统一个入口)。

  • 构建工具:vue-cli-service

  • 技术栈:vue 2.6 + Axios + Vuex + Vue-Router + sf-vue-componet(公司内部组件库) + ElementUI

  • 维护时长:3 年+,(实际上应该远远超过五年,这个项目是以一个已经维护了很久的项目为基础进行开发的,而当前最早的一条 commit 记录是 3 年前,但是这个基础项目已经开发很久时间了)

  • 模块数量:6000(npm run serve 时显示的模块数量)

  • 业务代码量:19.3W 行

  • 兼容性要求:IE11

项目的体量在公司内部只能算是中等,之所以挑选这个项目进行处理是因为对这个业务比较熟悉。话不多说,开搞。

思路分析

本次的目的不是直接用vite 替换 vue-cli,而是想同时保留vitevue-cli。除去影响开发体验也主要是集中在 dev 这一块的原因外,还有以下两点:

  • 产品需要兼容IE11,尚不清楚vite在此方面有多少坑。步子迈太大了,可能扯着胯。
  • rollup 打包机制毕竟和 webpack 还是不同,且业务也比较复杂。修改完成之后也很难保证所有业务都能测试到位。

webpackvite 本质上都是入口文件 + 依赖分析 + 模块转换。vite 是 使用的时候进行处理(vite 针对第三方库有同样会进行预处理),webpack则是先全部处理完毕。当浏览器天然支持ES module之后,实时处理变得可能。这也是vite 启动速度快的原因。

所以,从理论上来说,从Vue-cli迁移到 vite 是可行的。

开始迁移

step1 分析 vue.config.js

首先,我们先进行 vue.config.js 进行分析。主要是把一些插件,和比较特殊的配置整理出来。然后再去 vite 官网和社区查看,看是匹配的配置或者插件。把其中不匹配的部分进行解决,估计迁移也就差不多了。

分析完成之后主要两点无法匹配的情况

// vue.config.js
module.exports = {
    chainWebpack: config => {
        config.plugins.delete('preload-loginPlatform');
        config.plugins.delete('prefetch-loginPlatform');
        config.plugins.delete('preload-platform');
        config.plugins.delete('prefetch-platform');
    },
    transpileDependencies: ['@sxf/cloudsec-components', '@sxf/validations', '@sxf/sf-vue-component']
}

chainWebpack 中的配置主要是为了解决两个入口资源互相加载的问题,即访问登录页时,会预加载管理系统资源。由于这个是打包后在生产环境中才会用到的内容,且这次迁移无需关系打包的内容,所以暂时不用处理。

transpileDependencies 主要是让 node_modules 中的文件也进行 babel 的处理,而我们在开发时可以使用最新的浏览器,完全可以不用 babel,所以这个问题也不用处理。

cli.vuejs.org/zh/config/#…

step2 安装依赖,添加 scripts

一般情况下,会需要用到以下的 npm 包。

  • vite
  • vite-plugin-vue2:vite 支持 vue2 的插件(默认情况下,vite 并不支持 vue)
  • vite-plugin-eslint(可选):vite eslint 插件,用于在 run dev 时,实时校验 eslint
  • vite-plugin-legacy(可选):处理浏览器兼容性,本次这里不需要。
  • vite-plugin-mock(可选):mock 数据
yarn add vite vite-plugin-vue2 -D # 这里只安装了必要的vite 与 vite vue2插件

然后添加 package.json 中 添加 scripts 命令。

// package.json
{
    ...,
    "scirpts": {
        ...,
        "dev": "vite"
	}
}

step3 编写 vite.config.js 文件

因为原本的 vue.config.js 不是特别复杂,网上也有其他迁移的文章讲解如何迁移webpack配置,所以我这里直接粘贴结果。

const { createVuePlugin } = require('vite-plugin-vue2')
const { resolve } = require('path');
const config = require('./config');
module.exports = {
    server: {
        host: '0.0.0.0',
        https: true,
        port: 4433,
        proxy: {
            '/platform': {
                target: `https://${config.host}`,
                secure: false,
                changeOrigin: true,
                rewrite: (path) => path.replace(/^\/platform/, '')
            },
            ... // 
        }
    },
    resolve: {
        alias: {
            '@': resolve(__dirname, './src'),
            'src': resolve(__dirname, './src'),
            'home': resolve(__dirname, './src/home'),
            'components': resolve(__dirname, './src/components'),
            'assets': resolve(__dirname, './src/assets'),
            'utils': resolve(__dirname, './src/utils'),
        }
    },
    build: { // 这里是build时才会用到,所以这里可以省略
      rollupOptions: {
        input: {
          login: resolve(__dirname, './public/login_platform.html'),
          platform: resolve(__dirname, './public/platform.html')
        }
      }
    },
    plugins: [
        createVuePlugin()
    ]
}

从上面的结果来看其实只用写三个部分的内容:

  1. serve: 开发时的运行端口,以及数据请求的反向代理的规则
  2. alias: 别名
  3. plugins: 引入vite-plugin-vue2用于加载 vue 文件。

关于多入口

在项目介绍的时候说到,项目是一个多入口的文件。实际上在 vite 的开发环境中,多入口无需配置。启动文件之后直接访问对应的 html 资源即可。

关于 wp2vite

github.com/tnfe/wp2vit… (一个前端项目转换工具,可以让 webpack 项目支持 vite)

wp2vite 能够将根据你当前的 webpack 配置生成 vite 配置(支持 vue-cli),如果不想手写 vite.config.js 可以使用该工具进行自动转换。我是在撰写本文整理资料时,才发现有此工具。

wp2vite 转换的结果并非完全正确,存在以下问题。

  • alias 添加了一些莫名其妙的别名 (也有可能是 Feature :smile:)
  • proxy 配置 rewrite 不正确

以上两点,各位同学在参考的时候注意一下就行。

step 4 调整入口文件

vue-cli 有区别的是,vite 默认只能将 html 作为入口文件,所以需要对 HTML 内容进行调整。

别忘记给 script 标签添加 type="module"

<!-- index.html 主应用的入口文件 -->
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    ...
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>...</title>
    <!-- 添加这一行直接引入之前的 入口文件 -->
    + <script type="module" src="/src/main.js"></script>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but project doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

<!-- login.html 登录页的入口文件 -->
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    ...
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>...</title>
    <!-- 添加这一行直接引入之前的 入口文件 -->
    + <script type="module" src="/src/login.js"></script>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but project doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

step 5 npm run dev

直接运行 npm run dev,可以发现 vite 马上就开启了服务。相对于原来 70s 左右的时间,这快了可不止一星半点,简直就是火箭起飞。

image-20210906144343218

当然,服务的启动并不代表迁移已经完成。vite 更多的是在访问对应的资源时才会去处理内容。所以需要访问对应的页面来进行验证。而真正的迁移,才刚刚开始 :sob:

无尽采坑:阶段一

问题 1:URIError: URI malformed

vite 开启之后,访问登录页 https://localhost:4433/static/login_platform.html,报错 URIError: URI malformed

image-20210906145521690

这是decodeURIComponent函数在执行时报的错。

通过在错误堆栈中,加上 console 语句,得知出错的 URI 是/static/%3C%=%20BASE_URL%20%%3Efavicon.ico

对应的代码则是 login.html 中的代码,这里的 BASE_URL是 vue-cli 中模板变量的写法,这里可以修改为/public/favicon.ico(根据自己的目录结构调整,切勿盲目套用)

<link rel="icon" href="<%= BASE_URL %>favicon.ico">
=>
<link rel="icon" href="/public/favicon.ico">

修改完成之后,vite 则提示去掉 public 前缀,那我们直接去掉就行。

image-20210906150224403

问题 2:Failed to resolve import "xxx"

image-20210906154851425

提示找不到对应的 vue 文件(实际肯定是有)。经过查阅资料这一块主要是为了类型提示的问题(ts 的项目),vite 不在自动查找.vue 扩展名的文件。

这里只需要补全PageLogin.vue即可。 在这里补全.vue扩展名不太现实,因为项目里面大部分都是省略了扩展名的。好在官方给出了解决的方案,直接配置即可。

cn.vitejs.dev/config/#res…

resolve.extensions

  • 类型: string[]
  • 默认: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json']

导入时想要省略的扩展名列表。注意, 建议忽略自定义导入类型的扩展名(例如:.vue),因为它会影响 IDE 和类型支持。

关于问题 2

配置resolve.extensions的方式,并不能够完全的解决问题。这里卖个关子,后面会继续遇到因为缺少.vue扩展名而导致的问题。那里会给出完美的解决方案。

问题 3: less import

修复完问题 2 之后,继续访问页面。这个时候又出了新的问题。

image-20210906151020412

经过查阅资料,vite 对 less 和 sass 文件的 import 进行了优化的处理,不在需要在别名前添加 ~符号来进行识别。

vitejs.bootcss.com/guide/featu…

vite 为 Sass 和 Less 改进了 @import 解析,以保证 vite 别名也能被使用。另外,url() 中的相对路径引用的,与根文件不同目录中的 Sass/Less 文件会自动变基以保证正确性。

由于 Stylus API 限制,@import 别名和 URL 变基不支持 Stylus。

这里就只需要全局搜索然后全局替换就行,如果有发现全局没有替换到的(多了空格什么的),手动替换一下就行。

image-20210906151548730

问题 4:net::ERR_ABORTED 408 (Request Timeout)

修复好问题 3,再次访问时出现很多资源 408 的错误。

image-20210906152826856

出现这个问题不要慌,重新刷新即可,这是 vite 在对一些依赖进行预构建。因为是请求到对应的资源才会进行预构建,在碰到需要预构建的包后,vite 直接返回了408

有时候需要重新刷新多次,每次构建完成之后重新刷新,如果发现新的需要预构建的依赖会再次返回408

image-20210906153255734

至于这里为什么返回408,而不是直接挂起请求预构建完成之后再返回,个人不是很清楚。有了解 vite 原理的同学可以解答下。

vitejs.bootcss.com/guide/dep-p…

vite 将有许多内部模块的 ESM 依赖关系转换为单个模块,以提高后续页面加载性能。

一些包将它们的 ES 模块构建作为许多单独的文件相互导入。例如,lodash-es 有超过 600 个内置模块!当我们执行 import { debounce } from 'lodash-es' 时,浏览器同时发出 600 多个 HTTP 请求!尽管服务器在处理这些请求时没有问题,但大量的请求会在浏览器端造成网络拥塞,导致页面的加载速度相当慢。

通过预构建 lodash-es 成为一个模块,我们就只需要一个 HTTP 请求了!

问题 5:Vue warn:runtime-only

等待所有内容都预构建完成之后,又出现了新的问题。

image-20210906153921859

这里问题比较好理解,vue 的默认引用的内容是不包含模板编译功能的。因为之前使用的是 vue-cli,毕竟是一家的东西 vue-cli 针对这个情况做了特殊的处理。

这种情况在 vite.config.js 中,添加一条别名即可解决。

github.com/underfin/vi…

// vite.config.js
{
    resolve: {
        alias: {
            '@': resolve(__dirname, './src'),
            ......,
            'vue': require.resolve('vue/dist/vue.esm.js')
        }
    }
 }

问题 6:require is not defined

image-20210906160418206

这里继续爆出来 import 的问题,但是这里肯定不是因为确实 .vue 扩展名引起的。经过分析,问题的原因是业务代码中使用了 require 语句,而 vite 主要是依赖于 ES module 机制。这也就导致无法识别该业务代码,进而导致该模块加载失败。

这里吐槽下,这里 vite 控制台 和 浏览器控制台爆出了不同的错误,而 vite 控制台的错误信息完全没法排查思路。

而在迁移前期,一直盯着 vite 控制台,这就导致一个很简单的问题实际上花费了很多的时间。

这种情况下,需要手动对业务代码进行处理。

{
    image: require('@uedc/login/dist/static/copyright/copyright-zh_CN@2016-2021.png')
}
// => 
import copyright from '@uedc/login/dist/static/copyright/copyright-zh_CN@2016-2021.png';
{
    image
}

采坑阶段一总结

修改完上述问题之后,本项目的多入口应用中的一个登录页面入口,终于可以正常展示了。

masaike.png

  • vite 控制台,chrome 控制台均无报错
  • 之前修改的 require 改为 import 的 logo,正常显示
  • 通过网络请加载的验证码,正常显示(说明反向代理这些都是正常的)

虽然遇到问题还是比较多,但是解决起来都不是很费时间,排查起来也比较顺利。至此迁移工作可以说已经进行了一半。除去 html 模板文件中修改favicon.ico 和导入图片的requrie之外,没有改动其他的业务代码,对业务的入侵很小。

话不多说,输入账号密码,开启第二个阶段的采坑。

无尽采坑:阶段二

问题 7: uses lang html for template

image-20210906165431300

这是一个相当无语的错误,应该是vite-plugin-vue2插件的 bug。问题的原因是在 template 中,写了lang="html"

<template lang="html">
	<div>
        .....
    </div>
</template>

虽然模板默认就是 html,这个声明时多此一举,但是报错感觉不应该。

好在这个问题比较好解决,通过查找字符串全局替换即可。你问我为什么要多此一举要声明lang="html"?我也不知道,这不就是老项目的魅力嘛:slightly_smiling_face:。

image-20210906165833301

问题 8: npm 包出错

image-20210906170953982

这也是本次迁移过程中,最为棘手的问题。不止一个 npm 包出错,且出错的内容也不一样。有些出错可以通过 vite 的配置解决,有些则无法解决。

一般来说有以下几种方法来解决 npm 包报错的问题。

方法一:修改别名,指向源码

即在 vite.config.js 中添加 alias

'@sxf/sp-qrcode': resolve(__dirname, './node_modules/@sxf/sp-qrcode/src/index.js'),

这种方法适用于 npm 包的源码是用 ES module 规范编写的,且上传的 npm 包中包含了源码。

方法二:修改别名,指向 esm 格式的打包文件

修改方式同方法一,只不过是执行打包后的 esm 文件。

这种方式适用于 npm 包已经 build 了 esm 模块的内容,但是未在 packages.json 中提供 module 字段指向对应的文件。

一般开源的,使用人数较多的 npm 包不会出现这种情况,只是因为这次出问题有一些是内部的包,确实存在 build 了 esm 的文件,但是没有在 package.json 中指明的情况。

方案三:optimiziDep.include

cn.vitejs.dev/config/#opt…

默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。

从官网的文档的描述信息来看optimiziDep.include是无法解决 npm 包出错的问题。因为不管怎样,node_modules 中的内容都会被预构建。但是从实际的使用中来看

  • vite 2.4.4 中,optimiziDep.include能够解决部分 npm 加载的问题。
  • vite 2.5.3 中,optimiziDep.include不再起作用。

因为 vite 一直在高速迭代,保不齐部分情况下此方法依旧有用。

方案四:参考问题 10

问题 10 也是 npm 出问题,但是这个问题比较具有代表性,所以单独拿出来。

方案无:换个 npm 包,或者修改 npm 包

如果上面三种方案都无法解决,那就只能从 npm 包本身下手了。

对于自己内部维护 npm 包,可以重新打包一个 ES module 的文件并发布。这里推荐用 rollup 打包,能够很轻松的构建CommonJSES moduleUMDIIFE格式的文件

rollupjs.org/guide/en/#o…

对于第三方的 npm 包,出现这种情况应该是很久没有维护了,所以也应该换一个了。

问题 9:Failed to resolve entry (ops,same proplem)

出现问题原因与问题2相同,也是因为没有.vue扩展名的问题。

image-20210906185147837

@sxf/cloudsec-component是一个自己维护的业务组件库,基于基础的 UI 组件库,将一些常用的业务进行封装,单独发布一个 npm 包。主要是为了方便同一个开发团队维护多个产品(这点与公司组织架构有一定的关系,不在深究)。因为业务组件需要调试的原因,npm 发布的是.vue的源码。

同样因为保持着相同的编码规范,业务中对组件库的引用,以及组件库本身开发时的互相引用都是省略了.vue扩展的。

而以上两种方案都无法通过resolve.extensions解决。

在 vite 2.4.4 的版本中,配置了 resolve.extensions 之后,无法识别 vue-router 中的 () => import('foo/bar/baz')

这个问题在 vite 2.5.3 中进行了修复,如果出现了此类问题,可以升级一下 vite 版本。

解决方案一:人肉修改

人肉一个个修改,这种情况适用于刚开始不久的项目。但是对于一个维护数年的老项目来说,这基本不现实。20W 行左右的代码,几千个 vue 文件。作为程序员明显不能这么干活。

解决方案二:vite 插件

vite 插件的第一个例子就是讲的引入一个虚拟文件,这里的问题其实类似。就是没有补充扩展名,导致找不到,那么可以通过插件查找。

vitejs.bootcss.com/guide/api-p…

image-20210906191108879

这里提供一下伪代码,未进行实际的验证

因为这只是解决了 vite 加载的问题,但是没有解决类型提示的问题,这对于后续进行 ts 相关改造不友好,所以没有去验证此方案。

感兴趣的可以验证一下,个人在实际的业务中是采用的方案三。

module.exports = function () {
    return {
        name: 'vite-plugin-fix-vue-ext',
        resolveId(id) {
            // 判断是否需要补充后缀,如果需要则返回id,表示命中。
            if (isNeedFixExt(id)) return id;
        },
        load(id) {
            if (isNeedFixExt(id)) return fs.readFileSync(fixExt(id));
        }
    }
}

解决方案三:codemod

codemod 指的是 code modify,实际上指的就是修改代码本身,并且是通过代码修改代码,而不是人肉修改代码。

实际上 ESLint 的 auto fix 也是 codemod 的一种。

这里的思路是:

  1. 找到所有的 import 语句 和 动态 import 语句
  2. 提取 import 的值,过滤掉已经有扩展名的值。
  3. 对没有扩展名的值,处理成绝对路径(考虑相对路径,vite 别名),暂时称这个绝对路径为ap
  4. 然后对ap补齐['.js','.ts','.vue','/index.js','/index.ts','/index.vue']依次判断是否存在。如果.vue类型的存在,而其余类型的不存在则表示需要补齐后缀。
  5. 判断是否存在的方案可以是依次尝试读取对应文件,或者是全部预先读取建立 Map 以供查找。

原理大致就是这样,关键在于怎么获取所有 import,又如何修改对应的文件。

  • 方案一:利用 es-module-lexermagic-string。因为 vite 本身就是用的这两个包进行的裸模块重写,关于什么是裸模块重洗,可以看下掘金这边文章的,这里不再赘述。这个方案的好处是处理的效率非常的高,坏处就是只能针对 import 进行操作,场景比较单一。

    juejin.cn/post/699220…

  • 方案二:利用 jscodeshift,相对而言,jscodeshift是操作 AST,比方案一要慢,且要复杂很多。因为jscodeshift的通用性比较高,担心后续迁移过程中有其他的 codemod 的需求,所以还是选择了方案二。

    jscodeshift的 API 很复杂,官方的 github 上面也有很多 codemod 的示例。我们如果要开发则可以先在astexplorer.net/ 进行尝试。

首先,点开 Transform,并点击 jscodeshift。

image-20210906194050473

然后就可以边写代码边看结果。

image-20210906194623073

提取动态 import 的代码和正常 import 的代码如下

// 提取动态import
j(file.source)
    .find(j.ImportDeclaration)
    .forEach(path => {
        const importNode = j(path);
    	const importString = importNode.get('source');
    	importString.value.value = 'zzzzzzzz';
    })
    .toSource();

// 提取普通import
j(file.source)
    .find(j.ImportExpression) // 只修改了这里 ImportDeclaration => ImportExpression
    .forEach(path => {
        const importNode = j(path);
    	const importString = importNode.get('source');
    	importString.value.value = 'zzzzzzzz';
    })
    .toSource();

尝试判断文件是否存在的代码如下

// str 为import的字符串
// filename 为出现这个import 语句的绝对路径
const fixExtname = (str, fileName) => {
    let importAbsolutePath;
    // 处理 相对路径,别名等情况
    if (str.startsWith('./')) {
        importAbsolutePath = path.resolve(path.dirname(fileName), str);
    } else if (str.startsWith('../')) {
        importAbsolutePath = path.resolve(path.dirname(fileName), str);
    } else  {
        importAbsolutePath = fixAlias(str);
    }
    const tries = {
        '.js': '',
        '.ts': '',
        '.vue': '.vue',
        '/index.js': '',
        '/index.ts': '',
        '/index.vue': '/index.vue',
    }
    let ext = '';
    Object.keys(tries).forEach(key => {
        const p = importAbsolutePath + key;
        if (fs.existsSync(p)) {
            ext = tries[key];
        } else {
        }
    })
    return ext;
}

关于方案三

这里还有个问题就是 jscodeshit 无法支持.vue 文件,个人开发是基于公司的一个 codemod 工具,那里封装了对 vue 文件的识别。

识别 vue 文件也是通过 vue 官方的包解析就行了。如果大家有这方面强烈的需求,可以考虑把这些代码封装成一个单独的 jscodeshit 的 codemod。

问题 10: does not provide an export named 'default'

image-20210906203935807

这个问题是因为第三方的 npm 包是提供的是 CommonJS 规范的文件。

vitejs.bootcss.com/guide/dep-p…

CommonJS 和 UMD 兼容性: 开发阶段中,vite 的开发服务器将所有代码视为原生 ES 模块。因此,vite 必须先将作为 CommonJS 或 UMD 发布的依赖项转换为 ESM。

vite 官网说,会兼容CommonJS 格式的文件,但是这里为什么还是因为CommonJS格式的问题呢?

其实这个文件是可以 import 导入的只是并没有提供 default 这个属性,这么说 vite 也确实支持了CommonJS

遇到这种情况我们需要引入 @originjs/vite-plugin-CommonJS这个包

const { viteCommonJS } = require('@originjs/vite-plugin-CommonJS');
module.exports = {
    plugins: [
        viteCommonJS({
            include: ['procurios.resizesensor']
        }),
        createVuePlugin()
    ]
}

采坑阶段二总结

在 主入口页面的迁移过程中,改动了非常多的代码。

  • 业务代码293个文件
  • 业务组件的代码139个文件

但是修改这些文件大多数没有修改业务,只是补全了链接。但是 less 的文件 import 却是和 webpack 不兼容。

此外,还有有一些有问题的 npm 包,这次迁移的过程并没有完全解决,只是将对应的代码给注释。

最终通过以上措施,终于能够访问了,也看到了主入口的页面。

index.png

最终总结

vite 优点大家都知道,我主要来说一下现阶段的缺点。

总的来说现阶段的vite还存在以下问题:

  • 手动重新npm run dev后,预构建之后缓存丢失,而修改vite.config.js导致的自动重启不会。
  • 预构建需要访问到对应的文件才能触发,会导致频繁408,且速度非常慢。整个下来时间比较久,而且需要你手动刷新浏览器。比较奇怪的是vite 2.4.4 在这方面 比vite 2.5.3 快非常多,基本上只会出现一次408
  • 无法很好的处理非 ES module的 npm 包,与webpack还存在一定的差距。
  • 请求数量巨大,从 network 的面板来看,请求的数量高达468,除去XHR请求之外也有将近400个请求。所以首次加载的时间比较慢大概花了5秒,这一块应该是可以通过 vite 的配置来优化。等内部的一些 npm 包调整完毕能够进行正常的开发之后,会总结一些开发的实践并发出来。
  • 功能不稳定。在早期使用vite 2.4.4进行迁移时,问题稍微还多一些。之后更新到vite 2.5.3之后,部分问题被修复了,但是也增加了一些新的问题。

针对老项目需要迁移到 vite,需要考虑以下情况:

  • 不在支持非ES module的业务代码(如 require,module.exports),如果有这些代码需要进行调整,可以尝试与问题9相同的方式。
  • less/sass 的@import: vite 不在需要 ~ 来使用别名,这一点与 webpack 不兼容。
  • 因为 IE11 天然不支持ES module,所以 IE 调试比较麻烦,不建议需要支持 IE11 的项目将vite作为唯一的构建工具。
  • 现阶段的vite 对 npm 包有着较高的要求,迁移之前可以先看下项目的 npm 包,该替换的替换,该升级的升级。

整体来说,vite的开发体验比较好,轻量且快。即便是一个臃肿的老项目也能够做到反应迅速且不占用过多资源。项目较大时webpack启动时会占用大量的电脑资源,导致这一段时间 VSCode 非常卡,这一点体验非常不好。

总的来说vite 未来可期。

最后祝大家搬砖开心😃