版本
一、Vite 1.x
二、Vite 2.x
三、Vite 3.x
3.1 CLI 的更新
在执行 vite
命令启动项目时,终端的界面和之前会有所不同,而更重要的是,为了避免 Vite
开发服务的端口和别的应用冲突,默认的端口号从之前的 3000
变成了 5173
。
3.2 开箱即用的 WebSocket 连接策略
Vite 2
中有存在一个痛点,即在存在代理的情况下(比如 Web IDE
)需要我们手动配置 WebSocket
使 HMR
生效。目前 Vite
内置了一套更加完善的 WebSocket
连接策略,自动满足更多场景的 HMR
需求。
3.3 服务冷启动性能提升
Vite 3.0
在服务冷启动方面做了非常多的工作,来最大程度提升项目启动的速度。
首先我们来盘点一下 Vite 2.x
阶段服务冷启动的一些问题。
从 Vite 2.0
到 2.9
版本之前,Vite
会在服务启动之前进行依赖预构建,也就是使用 Esbuild
将项目中使用到的依赖扫描出来(Scan
),然后分别进行一次打包(Optimize
)。
这样会造成两个问题:
-
依赖预构建会阻塞
Dev Server
启动,但其实不阻塞的情况下,Dev Server
也可以正常启动。 -
当某些
Vite
插件手动注入了import
语句,比如调用babel-plugin-import
添加import Button from 'antd/lib/button'
,就会导致Vite
的二次预构建,因为antd/lib/button
的引入代码由Vite
插件注入,属于Dev Server
运行时发现的依赖,冷启动阶段无法扫描到。
所谓的二次预构建包含两个步骤,一是需要将所有的依赖全量预构建,二是由于依赖更新,页面需要进行 reload
,加载最新的依赖代码。这样会导致 Dev Server
性能明显下降,尤其是在新增依赖较多的场景下,很容易出现浏 览器卡住的情况。因此二次预构建也是需要极力避免的。当时 vite-plugin-optimize-persist
就是为了解决二次预构建带来的问题,通过持久化的方式记录 Dev Server
运行时扫描到的依赖,从而让首次预构建便可以感知到,避免二次预构建的发生。
到了 2.9
版本,Vite
将预构建的逻辑做了一次整体的重构,最后的效果是下面这样的:
-
Dev Server
启动后预构建(Optimize
阶段)在后台执行,也就是预构建不再阻塞Dev Server
的启动,只需要等待Scan
阶段完成,不过通常这个阶段的开销非常小。Preview -
如果某些依赖是
Dev Server
运行时才发现的,那么Vite
会尽可能地复用已有预构建产物,尽量不进行page reload
。
那问题就完全解决了吗?其实并不是,在某些场景下,Vite
仍然不可避免地需要二次预构建。如 下面的这个例子:
A
和 B
都是项目的第三方依赖,它们也同时依赖 C
。那么当 Vite
预构建 A
的时候,将会 A
和 C
一起进行打包。但 Vite
在运行时发现了依赖 B
,而 A
和 B
需要共享 C
的代码,这样 C
的代码可能就会被抽离成一个公共的 chunk
,因此之前 A
的预构建产物可能就发生变化了,那么此时 Vite
必须要强制刷新页面,让浏览器使用最新的预构建产物。这仍然是一个二次预构建(所有依赖再次打包 + page reload
)的过程。
总体而言,2.9
版本解决了预构建阻塞服务启动的问题,但并没有完全解决二次预构建的问题。
但在 Vite 3.0
,二次预构建的问题也得到了根本的解决。那 Vite 3.0
是如何做到的呢?
核心的解决思路