Vite,一个基于浏览器原生 ES imports 的开发服务器。
利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。
同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢。
针对生产环境则可以把同一份代码用 rollup 打。虽然现在还比较粗糙,但这个方向我觉得是有潜力的,做得好可以彻底解决改一行代码等半天热更新的问题。
--尤雨溪微博
一、Webpack
原理:
webpack 用类似于node 的commonjs的模块方案,将最终打包的代码运行在浏览器中。所有的模块都通过 webpack_require 进行加载,并且会把加载完成的模块进行缓存。
存在的问题
- 概念和配置项太多,需要配合实际的项目场景不断的优化配置文件,vue-cli等脚手架就是为了解决无法开箱即用的问题;
- 随着项目的不断变大,devServer的启动时间会越来越长,并且hmr的速度也会受到影响。
二、Vite出现背景
- Http2.0 的出现
- 对于ES module的支持,主流的现代浏览器已经有这不错的兼容性,随着使用者的升级,这个覆盖率会越来越高。\
因此,似乎可以利用 http/2 和 浏览器对 ES module 的支持,来直接加载代码,而不再需要进行代码的打包。
在es6中,加入了JavaScript的模块。
只需要在script标签上加上 type=module 的属性,浏览器就会将内联代码或者外部引用的脚本视为ECMAScript模块。\在浏览器里使用 ES module 是使用 http 请求拿到模块的,所以 file 协议的请求不允许。
三、更快的速度
首先,我们对比一下 vite 与 webpack 的启动一个 vue hello world 时间。
从上面的例子中可以看到 Webpack 启动服务的时间较长一些,但是页面加载性能是好于 vite 的。
3.1 Bundleless
Vite 直接使用ES Module,利用浏览器去解析文件中import的依赖,对于使用到的依赖通过请求去获得相应的资源文件,最后生成代码的时候不需要任何的构建,直接把ES module的代码抛给浏览器即可。
从而不再需要像Webpack那样,从入口文件entry出发,收集所有的依赖然后整体打包,最后把打包的bundle文件交给浏览器解析运行。
3.2 极速的hmr
Vite 不会因为模块数量的膨胀而造成热更新的速度变慢,因为 Vite 不像 Webpack 需要构建一份全量的依赖图,并且这份依赖图有可能在模块依赖特别复杂的时候会造成热更新的不准确
devServer使用304来进行协商缓存,对于已经加载过的模块,会增加Cache-Control: max-age=31536000 来做缓存,减少网络请求
上图是snowpack和webpack 热更新所需时间的对比。
热更新的时候,Vite 只需要立即编译当前所修改的文件即可,所以 响应速度非常快。修改了App.vue,只会去编译当前修改的。
而 Webpack 修改某个文件过后,会自动以这个文件为入口重写 build—次,所有的涉及到的依赖也都会被加载一遍,所以反应速度会慢很多。
3.2 真正的按需编译
Vite 通过浏览器的解析来进行依赖资源的加载,所以在文件没有被使用之前,所有的依赖文件都不用进行处理,真正做到了按需编译。
Webpack 的spa模式很难进行按需编译,因为从入口文件开始,会做完所有的依赖分析和处理,就算是进行了按需加载的模块,也还是会被编译。
另一个可行的方案是mpa,但是就脱离了单页应用的开发模式了,并且项目在开发和发布的时候复杂度都会增加。
上面两张图片可以直观的看出Vite在编译上的优势,项目只需要在路由层面进行按需加载,就能够做到按需编译。
这里需要注意的是,如果项目没有对路由进行按需加载的处理,最后还是会一次性编译加载所有的依赖
3.3 极速的编译速度
Vite 使用 Esbuild 来进行代码的编译,其中jsx和tsx都是通过Esbuild解析生成AST,再生成最终的es module的代码,commonjs到ES module也使用它来进行转换
Esbuild是使用Go语言进行开发的,并且发布的是进行编译过的更底层的机器码,在执行效率上远远高于JavaScript编写的打包器,预期会快10-100百倍
在 Vite 1.0 中,使用 rollup 的 @rollup/plugin-commonjs 来实现commonjs转换成ES6,在Vite 2.0 中,使用esbuild来处理模块转换,大大提高了效率
3.4 依赖预构建
在 Vite 首次运行的时候,会从入口文件出发,对其中的第三方依赖进行分析和打包,并把这些chunk进行缓存,提高页面的加载速度。
很多第三方的依赖都是commonjs和umd的模块,通过预构建,用 esbuild 将模块转换为ESM,这样这些第三方的包就能在浏览器中直接运行了。
将多入口的模块,比如lodash,转换成单文件的模块,减少网络请求,提高页面的加载性能
3.5 开箱即用
除了对于Vue的第一优先级的支持,Vite 还在内部内置了大量默认的处理,比如支持jsx和tsx,样式预处理库支持less、sass 和 CSS module
完整的脚手架工具链,可以快速生成Vue、React等项目的模板,提供了大量的配置项,作者说后期有可能会替换掉vue-cli。
和vue、vue-cli 一样优秀又友好的文档,并且有对应的中文文档
四、不足
- Esbuild 现在还不够稳定,无法用于生产环境的打包,项目打包的时候需要使用Rollup,这就造成开发环境和生产环境的代码不一致,有可能一些bug会无法定位
- 浏览器的支持度还有待提升
- ssr还在试验阶段