知识储备
- 掌握ES Modules特性
- 了解HTTP 2标准
相关介绍
Vite的定义
面向现代浏览器的一个更轻、更快的Web应用开发工具,
基于ECMAScript标准原生模块系统(ES Modules)实现
Vite的由来
如果应用比较复杂,使用Webpack的开发过程相对没有那么丝滑。
- Webpack Dev Server冷启动时间会比较长
- Webpack HMR热更新的反应速度比较慢
快速上手
Vite官方目前提供了一个比较简单的脚手架:create-vite-app,可以使用这个脚手架快速创 建一个使用Vite构建的Vue.js应用
1 | $ npm init vite-app <project-name> |
如果使用yarn:1
2
3
4$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev
RS. npm init或者yarn create是这两个包管理工具提供的新功能,其内部就是自动 去安装一个create-
的模块(临时),然后自动执行这个模块中的bin。例如: yarn create react-app my-react-app 就相当于先 yarn global add create-react-app ,然后自动执行 create-react-app my-react-app
对比差异点
打开生成的项目过后,你会发现就是一个很普通的Vue.js应用,没有太多特殊的地方。
不过相比于之前vue-cli创建的项目或者是基于Webpack搭建的Vue.js项目,这里的开发 依赖非常简单,只有vite* @vue/compiler-sfc。
vite就是我们今天要介绍的主角,而@vue/compiler-sfc就是用来编译我们项目中.vue结 尾的单文件组件(SFC),它取代的就是Vue.js2.x时使用的vue-template-compiler。
再者就是Vue.js的版本是3.0。这里尤其需要注意:Vite目前只支持Vue.js 3.0版本。
如果你想,在后面介绍完实现原理过后,你也可以改造Vite让它支持Vue.js 2.0。
基础体验
这里我们所安装的vite模块提供了两个子命令:
- serve:启动一个用于开发的服务器
- build:构建整个项目(上线)
当我们执行vite serve的时候,你会发现响应速度非常快,几乎就是秒开。
可能单独体验你不会有太明显的感觉,你可以对比使用vue-cli-service (内部还是 Webpack)启动开发服务器,
当我们对比使用vue-cli-service serve的时候,你会有更明显的感觉。
因为Webpack Dev Server在启动时,需要先build—遍,而build的过程是需要耗费很多时 间的。
而Vite则完全不同,当我们执行vite serve时,内部直接启动了 Web Server,并不会先编译所有的代码文件。
那仅仅是启动Web Server,速度上自然就快了很多。
但是像Webpack这类工具的做法是将所有模块提前编译、打包进bundle里,换句话说,不 管模块是否会被执行,都要被编译和打包到bundle里。随着项目越来越大打包后的bundle 也越来越大,打包的速度自然也就越来越慢。
Vite利用现代浏览器原生支持ESM特性,省略了对模块的打包。
对于需要编译的文件,Vite采用的是另外一种模式:即时编译。
也就是说,只有具体去请求某个文件时才会编译这个文件。
所以,这种「即时编译」的好处主要体现在:按需编译。
Optimize
Vite还提供了一个目前在帮助列表中并没有呈现的一个子命令:optimize 这个命令的作用就是单独的去「优化依赖」。
所谓的「优化依赖」,指的就是自动去把代码中依赖的第三方模块提前编译出来。
例如,我们在代码中通过import载入了 VUe这个模块,那通过这个命令就会自动将这个模 块打包成一■个单独的 ESM bundle,放到 node_modules/• vite_opt_cache 目录中。
这样后续请求这个文件时就不需要再即时去加载了。
HMR
同样也是模式的问题,热更新的时候,Vite只需要立即编译当前所修改的文件即可,所以 响应速度非常快。
而Webpack修改某个文件过后,会自动以这个文件为入口重写build—次,所有的涉及到 的依赖也都会被加载一遍,所以反应速度会慢很多。
Build
Vite在生产模式下打包,需要使用vite build命令。
这个命令内部采用的是Rollup完成的应用打包,最终还是会把文件都提前编译并打包到一 起。
对于Code Splitting需求,Vite内部采用的就是原生Dynamic imports特性实现的,所以
打包结果还是只能够支持现代浏览器。
不过好在 Dynamic imports 特性是可以有 Polyfill 的:https://github_com/GoogleChromeL abs/dynamic-import-polyfill,也就是说,只要你想,它也可以运行在相对低版本的浏览器 中。
打包or不打包
Vite的出现,引发了另外一个值得我们思考的问题:究竟还有没有必要打包应用?
之前我们使用Webpack打包应用代码,使之成为一个bundle.js,主要有两个原因:
- 浏览器环境并不支持模块化
- 零散的模块文件会产生大量的HTTP请求
随着浏览器的对ES标准支持的逐渐完善,第一个问题已经慢慢不存在了。现阶段绝大多数 浏览器都是支持ES Modules的。
零散模块文件确实会产生大量的HTTP请求,而大量的HTTP请求在浏览器端就会并发请 求资源的问题;
如上图所示,红色圈出来的请求就是并行请求,但是后面的请求就因为域名链接数已超过限 制,而被挂起等待了一段时间。
在HTTP 1.1的标准下,每次请求都需要单独建立TCP链接,经过完整的通讯过程,非常耗 时;
而且每次请求除了请求体中的内容,请求头中也会包含很多数据,大量请求的情况下也会浪 费很多资源。
但是这些问题随着HTTP 2的出现,也就不复存在了。
关于HTTP 1.1与 HTTP 2之间的差异,可以通过这个链接体验:https://http2.akamai.com /demo,直观感受下HTTP/2比HTTP/1到底快了多少。
而且不打包也有一个好处,就是可以把按需加载实现到极致。
关于HTTP 2的详细介绍,可以参考:
- https://blog.fundebugxom/2019/03/07/understand-http2-and-http3/
- https://www.digitalocean.com/community/tutorials/http-l-l-vs-http-2-what-s-the -difference
开箱即用
- Typescript-内置支持
- less/sass/stylus/postcss -内置支持(需要单独安装所对应的编译器)
特性小结
Vite带来的优势主要体现在提升开发者在开发过程中的体验。
- Dev Server无需等待,即时启动;
- 几乎实时的模块热更新;
- 所需文件按需编译,避免编译用不到的文件;
- 开箱即用,避免各种Loader和Plugin的配置;
实现原理
Vite 的核心功能:Static Server + Compile + HMR
核心思路:
- 将当前项目目录作为静态文件服务器的根目录
- 拦截部分文件请求
- 处理代码中importnode_modules中的模块 b•处理vue单文件组件(SFC)的编译 3•通过 WebSocket 实现 HMR
手写实现
详细参考my-vite https://github.com/libin1991/my-vite
1 |
|