Vite是Vue框架的作者尤雨溪为Vue 3开发的新的构建工具,目的是替代Webpack,其原理是利用现代浏览器已经支持ES6的动态import,当遇到import时会发送一个HTTP请求去加载文件,Vite会拦截这些请求,进行预编译,省去了Webpack冗长的打包时间,提升开发体验。Vite构建工具的Logo如图3-24所示。
图3-24 Vite构建工具Logo
Vite借鉴了Snowpack,在生产环境使用Rollup打包。相比Snowpack,它支持多页面、库模式、动态导入、自动polyfill等。
Vite开源网址为https://github.com/vitejs/vite,Vite官方网址为https://vitejs.dev/。
Vite解决了Webpack开发阶段Dev Server冷启动时间过长,HMR(热更新)反应速度慢的问题。早期的浏览器基本上不支持ES Module,这个时候需要使用Webpack、Rollup、Parcel等打包构建工具来提取、处理、连接和打包源码,但是当项目变得越来越复杂,模块数量越来越多时,特别是在开发过程中,启动一个Dev Server所需要的时间也会变得越来越长,当编辑代码、保存、使有HRM功能时,可能也要花费几秒才能反映到页面中。这种开发体验是非常耗时的,同时体验也非常差,而Vite就是为解决这种开发体验上的问题的。总体来讲Vite有以下优点:
(1)去掉打包步骤,快速地冷启动。
(2)及时进行模块热更新,不会随着模块变多而使热更新变慢。
(3)真正按需编译。
Vite不仅支持Vue 3项目构建,同时也支持其他的前端流行框架的项目构建,目前支持的框架有vanilla、vanilla-ts、vue、vue-ts、react、react-ts、preact、preact-ts、lit、lit-ts、svelte、svelte-ts。
注意: Vite需要Node.js版本不低于12.0.0版,然而,有些模板需要依赖更高的Node版本才能正常运行,当包管理器发出警告时,需要注意升级Node版本。
安装Vite,同时使用Vue 3模板构建项目,命令如下:
命令执行的结果如图3-25所示。
图3-25 创建项目成功提示
接下来,进入my-vue-app目录,执行yarn命令安装依赖包,再执行yarn dev命令启动项目,如图3-26所示。
在浏览器中预览的效果如图3-27所示。
图3-26 执行yarn dev命令启动项目
图3-27 预览Vue 3+Vite项目效果
安装Vite,同时使用React模板构建项目,命令如下:
创建的项目结构如图3-28所示。
在项目目录下,执行yarn dev命令,启动项目,在浏览器中预览效果,如图3-29所示。
图3-28 Vite+React项目的目录结构
图3-29 预览Vite+React项目效果
在介绍Vite原理之前,需要先了解打包模式(Bundle)和无打包模式(Bundleless)。Vite借鉴了Snowpack,采用无打包模式。无打包模式只会编译代码,不会打包,因此构建速度极快,与打包模式相比时间缩短了90%以上。
2015年之前,前端开发需要打包工具来解决前端工程化构建的问题,主要原因在于网络协议HTTP 1.1标准有并行连接限制,浏览器方面也不支持模块系统(如CommonJS包不能直接在浏览器运行),同时存在代码依赖关系与顺序管理问题。
但随着2015年ESM标准发布后,网络通信协议也发展到多路并用的HTTP 2标准,目前大部分浏览器已经支持了HTTP 2标准和浏览器的ES Module,与此同时,随着前端工程体积的日益增长与亟待提升的构建性能之间的矛盾越来越突出,无打包模式逐渐发展兴起。
打包模式与无打包模式对比如表3-9所示。
表3-9 打包模式与无打包模式对比
开发模式:Vite提供了一个开发服务器,然后结合原生的ESM,当代码中出现import时,发送一个资源请求,Vite开发服务器拦截请求,根据不同的文件类型,在服务器端完成模块的改写(例如单文件的解析、编译等)和请求处理,实现真正的按需编译,然后返回浏览器。请求的资源在服务器端按需编译返回,完全跳过了打包这个概念,不需要生成一个大的包。服务器随启随用,所以开发环境下的初次启动是非常快的,而且热更新的速度不会随着模块增多而变慢,因为代码改动后,并不会有打包的过程。
Vite本地开发服务器所有逻辑基本依赖中间件实现,如图3-30所示,中间件拦截请求之后,主要负责以下内容:
图3-30 拦截不同的资源请求,实时编译转换
(1)处理ESM语法,例如将业务代码中的import第三方依赖路径转换为浏览器可识别的依赖路径。
(2)对.ts、.vue等文件进行即时编译。
(3)对Sass/Less等需要预编译的模块进行编译。
(4)和浏览器端建立socket连接,实现HMR。
生产模式:利用Rollup来构建源码,Vite将需要处理的代码分为以下两大类。
第三方依赖:这类代码大部分是纯JavaScript代码,而且不会经常变化,Vite会通过pre-bundle的方式来处理这部分代码。Vite 2使用ESBulid来构建这部分代码,ESBuild是基于Go语言实现的,处理速度会比用JavaScript写的打包器快10~100倍,这也是Vite为什么在开发阶段处理代码很快的一个原因。
业务代码:通常这部分代码不是纯的JavaScript(例如JSX、Vue等)代码,经常会被修改,而且也不需要一次性全部加载(可以根据路由进行代码分割后加载)。
由于Vite使用了原生的ESM,所以Vite本身只要按需编译代码,然后启动静态服务器就可以了。只有当浏览器请求这些模块时,这些模块才会被编译,以便动态加载到当前页面中。