可以分为两个层面,前端开发工具和构建工具,说明
Vite
在开发过程中与构建项目中有极致的体验提升
1 ESM (ECMAScript Module)
CommonJs 社区规范
ES6之前,服务端的规范
// CommonJS模块,运行时加载
let { stat, exists, readfile } = require('fs')
复制代码
具有以下特点
- 动态解析 运行时加载模块
- 加载整个模块
commonJS
模块中,导出的是整个模块 - 每个模块皆为对象
commonJS
模块都被视作一个对象 - 值拷贝
commonJS
的模块输出和函数的值传递相似,都是值的拷贝
AMD、UMD 社区规范
ES6之前,客户端的规范
- 如上
- 异步加载
ES Module 官方规范
ES6之后
// ES6模块,编译时加载
import { stat, exists, readFile } from 'fs';
复制代码
具有以下特点
- 静态解析 即在解析阶段就确定输出的模块,所以
es6
模块的import
一般写在被引入文件的开头。 - 加载的不是整个模块 在
es6
模块中经常会看见一个模块中有好几个export
导出 - 模块不是对象 在
es6
里,每个模块并不会当做一个对象看待 - 模块的引用
es6
模块中,导出的并不是模块的值拷贝,而是这个模块的引用
浏览器是怎么加载ESM的
<!-- ES6 模块 -->
<script type="module" src="./entry.js"></script>
复制代码
浏览器加载ESM也使用<script>
标签,但是要加入type="module"
属性。异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本。如果网页有多个ESM
,它们会按照在页面出现的顺序依次执行。
ESM在浏览器的兼容性
2 为什么使用Vite
- 缓慢的服务器启动,打包时间久
- 缓慢的热更新,更新一个模块,全局打包
- 缓慢的构建流程
3 开发环境使用Vite
快速冷启动
Webpack:先经过打包,生成 bundle
文件,再启动本地服务器
Vite:先启动本地服务器,不打包,不编译,Vite 使用 esbuild
预构建依赖。
esbuild
使用 Go
编写,并且比以 JavaScript
编写的打包器预构建依赖快 10-100
倍。
按需编译
访问入口,根据http请求路径,加载对应的模块依赖,只有访问到的资源和模块依赖才会进行编译,将vue
等浏览器不能识别的文件编译为ESM
,返回给浏览器
热重载(HMR)
Webpack:一旦保存必经过打包,生成新的 bundle
文件,再启动本地服务器,随着项目的复杂度提升打包时间增加,等待热重载需要漫长的时间
Vite:对于已加载的模块进行缓存,精准将改动的 vue
等浏览器不能识别的文件再次编译为 ESM
,毫秒级更新,不依赖项目的大小
4 生产环境使用Vite
为什么使用 rollup
进行打包
- 轻量,基于 ESM 的打包器
- 打包后的 bundle 文件体积更小
- 结合
tree-shaking
,删除未引用代码(Dead code)
为什么生产环境仍需打包
- 尽管原生 ESM 现在得到了广泛支持,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用
HTTP/2
) - 为了在生产环境中获得最佳的加载性能,最好还是将代码进行
tree-shaking
、懒加载和 chunk 分割(以获得更好的缓存) - 要确保开发服务器和生产环境构建之间的最优输出和行为一致并不容易。所以 Vite 附带了一套 构建优化 的 构建命令,开箱即用
为何不用 ESBuild
打包?
- 虽然 esbuild 快得惊人,并且已经是一个在构建库方面比较出色的工具,但一些针对构建应用的重要功能仍然还在持续开发中 —— 特别是代码分割和 CSS 处理方面
- 就目前来说,Rollup 在应用打包方面更加成熟和灵活。未来也不排除使用 esbuild 作为生产构建器的可能
5 拓展
特性
- 将原本
webpack
大部分工作交给浏览器去完成 - 使用
esbuild
预构建,CommonJS / UMD 转换为 ESM 格式,Vite 将有许多内部模块的 ESM 依赖关系转换为单个模块,以提高后续页面加载性能(eg:lodash-es
) - 天然支持
typescript
- 支持
less
,sass
等,只需要安装对应编译器,不需要写loader
配置等
ESM与Tree-shaking
ESM静态解析,rollup打包编译过程中,结合 tree-shaking
,删除未引用的代码(Dead code)
生产环境兼容性
用于生产环境的构建包会假设目标浏览器支持现代 JavaScript
语法,默认情况下,vite 的目标浏览器是指能够支持原生 ESM script
标签和支持原生ESM动态导入的
传统浏览器可以通过插件 @vitejs/plugin-legacy
来支持,它将自动生成传统版本的 chunk
及与其相对应 ES 语言特性方面的 polyfill
,兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载\
Vite与Weex的可能性
-
是不是要用weex语法去开发?
-
vite怎么支持weex-vue-loader?
-
怎么去和App端交互?