vite迁移记录

为什么要迁移到vite

当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。基于 JavaScript 开发的工具就会开始遇到性能瓶颈:通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用模块热替换(HMR),文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
为了提高开发的幸福感和愉悦度,和提高开发效率的情况下,最近对一个项目进行了改造迁移,迁移完成后热更速度让我有了非常舒畅的感觉。

vite为什么这么快

在冷启动的时候,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。但是vite通过在一开始将应用中的模块区分为 依赖源码 两类。

  • 依赖 大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)。

    Vite 将会使用 esbuild 预构建依赖。esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。

  • 源码 通常包含一些并非直接是 JavaScript 的文件,需要转换(例如 JSX,CSS 或者 Vue 组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。

Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。

Webpack 式的经典 bundler 示意图

img.png

Vite 式的 No-bundler 示意图

img_1.png

Vite能兼容IE吗

使用官方插件 @vitejs/plugin-legacy 支持

环境要求是什么

最低要求Node14.18.0+

开始迁移

必备插件

  • 必要的依赖:vite-plugin-html, vite,
  • Vue 3 单文件组件支持:@vitejs/plugin-vue
  • Vue 3 JSX 支持:@vitejs/plugin-vue-jsx
  • Vue 2.7 支持:vitejs/vite-plugin-vue2
  • Vue <2.7 的支持:underfin/vite-plugin-vue2

Eslint集成

我们在awesome-vite库中可能会看到两个Eslint插件,那么他们有什么不同呢?
在这里了推荐使用@nabla/vite-plugin-eslint,为什么呢?

相较于vite-plugin-eslint,上面推荐的可以保持HMR迅速,因为linting是异步完成的,不会阻塞编译的进行,而这个插件会先检查linting再编译,这样我们的HMR就变慢了。

环境变量区分

Vite 使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量:

.env                # 所有情况下都会加载
.env.local          # 所有情况下都会加载,但会被 git 忽略
.env.[mode]         # 只在指定模式下加载
.env.[mode].local   # 只在指定模式下加载,但会被 git 忽略

mode是怎么配置的,可以在启动vite的时候添加--mode ${你的mode}

遇到的问题

我们使用了非阻塞的eslint会导致构建抛出的告警不终止构建,这个时候就可以在构建前进行手动eslint检查

img_6.png

with语法的问题

在vite启动构建依赖的时候esbuild会出现with语法不能兼容的情况,这个时候这个包只能通过使用js去请求一个 script的方法来规避

npm的包没有指定入口文件

由于vite解析需要依赖入口文件,在没有配置的情况下,需要在引入的时候需要指定到具体的文件

其他注意事项

  • 使用 CommonJS 规范语法,例如 require('**');

    • 1.请转换为ESM语法

      img_2.png

    • 2.使用 Web API new URL

![img_3.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1987892252d444f1a97f969a5daf34d6~tplv-k3u1fbpfcp-watermark.image?)
  • 包含多个别名的导入,如:@import '~@/styles/global.scss',同时包含了别名 ~ 和 @

    • 您可以添加别名配置
      { find: /^~@/, replacement: path.resolve(__dirname, 'src') }resolve.alias 配置中,并且把该项配置移到别名配置中的第一项
  • 对于 Webpack 语法 require.context

    • 在vite中使用import.meta.glob替换
  • Webpack全局变量变更

    • 使用define配置选项

      img_4.png

  • 全局环境变量变更

    • process.env 使用import.meta.env代替
  • 装新依赖包后重启发现还是旧的包

    • 需要使用force进行重启

      img_5.png

构建生产版本

浏览器兼容性

Vite的默认目标是支持原生ESM和import.meta的浏览器,chrome> 87,这个情况下很显然是不能满足我们的,我们需要配置一个build.target进行改变兼容性,由于vite的转换过程是由esbuild进行的,那么只需要查看一下esbuild的选项,比如我现在迁移的项目是要支持WebRTC的,那么我只需要配置一个

build: {
     target: 'chrome55'
}

这样就会转换到兼容的选项了

原理解析

npm包依赖解析的预构建

在浏览器中原生 ES 导入不支持下面这样的裸模块导入,

import { someMethod } from 'my-dep'

上面的代码会在浏览器中抛出一个错误。因为浏览器是找到my-dep的路径的,所以Vite 将会检测到所有被加载的源文件中的此类裸模块导入,并执行以下操作:

  1. 预构建 它们可以提高页面加载速度,并将 CommonJS / UMD 转换为 ESM 格式。预构建这一步由 esbuild 执行,这使得 Vite 的冷启动时间比任何基于 JavaScript 的打包器都要快得多。
  2. 重写导入为合法的 URL,例如 /node_modules/.vite/deps/my-dep.js?v=f3sf2ebd 以便浏览器能够正确导入它们。

模块热替换

Vite 的热更新原理,其实就是在浏览器与vite服务端建立了一个 websocket 连接,服务端监听代码变动,当代码被修改后,服务端发送socket消息通知客户端去请求修改模块的代码,完成热更新。

TypeScript

Vite 使用 esbuild 将 TypeScript 转译到 JavaScript,约是 tsc 速度的 20~30 倍,同时 HMR 更新反映到浏览器的时间小于 50ms。

速度对比

启动速度对比

项目vitewebpack
冷启动4.895s1:38.585 s
热启动2.289s

vite 热启动时间

img_8.png

webpack启动速度时间

img_7.png

构建速度对比

项目vitewebpack
带sourceMap59.66s3:24.553s
不带sourceMap42.09s1:27.630s

可以看到构建的速度是大幅度的缩短了的

vite 带sourceMap时间

img_9.png

vite不带sourceMap时间

img_10.png

webpack 带sourceMap时间

img_11.png

webpack不带sourceMap时间

img_12.png

想要npm link进行vite调试?

在开发的时候难免会有一些需要本地调试的一些包,那么我们应该如何进行配置呢,如果是CJS的包,建议使用ESM的来进行调试,不然只能用--force进行重启。如果使用的是webpakck,建议升级到Webpack5,配置moudule的输出,详情可以查看webpack的文档进行配置。

配置ESM的npm link

我们首先要知道npm link的原理是配置一个软连接指向另外一个目录,那么我们要让vite不对这个包进行依赖预构建,这个时候就要配置optimizeDepsexclude属性,添加对应的npm包,然后通过--force进行重启,这个时候你只要改被依赖的包,vite就会自动帮你刷新。浏览器中的network也要记得禁用缓存哦。

现存的问题

文件多的时候,第一次需要预编译的文件很多而且请求非常多,这样会导致第一次启动的白屏时间过长,这里有两个方案可以解决。

  1. 可以启用h2,这样就不会被限制为h1.1的6个请求。
  2. 可以配置warmup,让启动的时候就直接预处理所有文件。

好的插件推荐

插件合集

免去https证书告警

文件预热

这个插件可以让你启动vite后立刻进行文件预热,不需要等到请求后再编译,可以有效减少白屏时间

总结

这次迁移上线并没有发现什么异常。总体来说,现在vite已经比较成熟了,在商用项目上已经可以胜任了。而且构建和热更速度有了质的飞跃。


sxuan
37 声望2 粉丝