作者:maxin,未经授权禁止转载。
简介
vite发音[veet],在法语中是轻量、轻快的意思
开发环境通过koa启动本地服务,生产环境通过Rollup打包构建
特点
- dev server启动时间不超过300ms
- 模块热替换(HMR)更新不超过100ms
- 通过 esbuild 来支持TS/JSX的转化
- 按需加载
esbuild
esbuild底层使用的golang进行编写的,在对比传统web构建工具的打包速度上,具有明显的优势。编译Typescript的速度远超官方的tsc
对比vue-cli
vue3和包括10个组件的前提下,vite在开发服务器启动时间上相较于vue-cli速度提升幅度较大
传统打包工具的dev-server
- 本地运行前需要加载所有模块文件并导出bundle才能展示页面
- 包括对每个文件导入/导出关系的解析
- 将各个模块排序、重写、关联
- 应用越大,开发服务的启动速度也越慢
- 代码分割只针对于生产环境构建
基于浏览器ES module的dev-server
<script type="module">
- 浏览器可以解析ES module的import并发送http请求
- dev server拦截浏览器对模块的请求并返回处理后的结果
<script type="module">
ES Module的特点: - 模块代码只在加载后执行
- 模块引用相同js只加载一次
- 模块是单例
- 模块可以请求加载其他模块
- 支持循环依赖
- 默认在严格模式下执行
- 不共享全局命名空间
- 模块顶级this的值是undefined
- 模块var声明不会添加到window
目录结构
$ tree -L 3 -I 'node_modules' ./src
./src
├── client # 客户端运行代码,主要是客户端的 socket 通信以及 HMR 相关
│ ├── client.ts
│ ├── env.d.ts
│ ├── tsconfig.json
│ └── vueJsxCompat.ts
├── hmrPayload.ts # HMR 类型定义
└── node # 服务端运行代码
├── build # vite build 命令运行代码
│ ├── buildPluginAsset.ts
│ ├── buildPluginCss.ts
│ ├── buildPluginEsbuild.ts
│ ├── buildPluginHtml.ts
│ ├── buildPluginManifest.ts
│ ├── buildPluginReplace.ts
│ ├── buildPluginResolve.ts
│ ├── buildPluginWasm.ts
│ └── index.ts
├── cli.ts
├── config.ts
├── esbuildService.ts # esbuild 相关代码
├── index.ts
├── optimizer # 预优化
│ ├── entryAnalysisPlugin.ts
│ ├── index.ts
│ └── pluginAssets.ts
├── resolver.ts # 模块加载逻辑
├── server # koa服务使用的一些中间件
│ ├── index.ts
│ ├── serverPluginAssets.ts
│ ├── serverPluginClient.ts
│ ├── serverPluginCss.ts # 处理css和其他css预处理器文件
│ ├── serverPluginEnv.ts
│ ├── serverPluginEsbuild.ts
│ ├── serverPluginHmr.ts # 服务端热模块替换相关
│ ├── serverPluginHtml.ts
│ ├── serverPluginJson.ts
│ ├── serverPluginModuleResolve.ts # 处理 /@modules/:id 开头请求的文件
│ ├── serverPluginModuleRewrite.ts
│ ├── serverPluginProxy.ts
│ ├── serverPluginServeStatic.ts # koa静态服务器
│ ├── serverPluginSourceMap.ts
│ ├── serverPluginVue.ts # 处理.vue文件
│ ├── serverPluginWasm.ts
│ └── serverPluginWebWorker.ts
├── transform.ts
├── tsconfig.json
└── utils
├── babelParse.ts
├── createCertificate.ts
├── cssUtils.ts
├── fsUtils.ts
├── index.ts
├── openBrowser.ts
├── pathUtils.ts
├── resolveVue.ts
├── shims.d.ts
└── transformUtils.ts
vite做了些什么?
$ vite
- 执行package.json的bin字段对应的js
- createServer
- 初始化koa、watcher、resolver
- 读取配置,合并到koa的context上
- 通过koa middlewares的方式使用一堆plugins
- 预优化用户项目里dependencies依赖的模块文件
koa中间件
vite中使用koa中间件的模式来处理请求到的不同类型文件,中间件的执行顺序类似于下图洋葱模型
来看一个简单的例子
执行顺序如下:
// 第一层洋葱 - 开始
// 第二层洋葱 - 开始
// 第三层洋葱 - 开始
// 第三层洋葱 - 结束
// 第二层洋葱 - 结束
// GET / - 2ms
// 第一层洋葱 - 结束
// 第一层洋葱 - 开始
请求拦截
- vite中使用的koa中间件
- 每个
plugin
都是一个函数 - 执行后use一个或多个中间件
- 在请求、响应的时候对资源文件进行解析、重写处理
- 返回给浏览器可直接执行的文件
如果import
后面的路径不是以 .
、./
、../
开头,浏览器不认识怎么办?
浏览器访问的时候,路径前缀已经被处理成/
、/@module/:id
开启--debug
模式,可以看到vite:rewrite
处理的路径重写
moduleRewritePlugin的作用:
- 对js文件进行拦截,包括*.vue文件中的
<template>
和<script>
- 把文件通过可读流转化成字符串内容并读取
- 使用esbuild提供的
es-module-lexer
进行词法分析 - 使用
magic-string
来替换import中无法识别的路径- 裸模块导入 vue -> @module/vue.js
- 相对路径导入 ./App.vue -> /src/App.vue
- 重写后的字符串拼到ctx.body上返回给下一个中间件
- 将ctx.path和重写后的文件拼接作为rewriteCache的key,文件作为value进行缓存
- 改写后的路径会再次向服务器拦截请求
- 下次path+file没变的话直接返回file
- rewriteCache是
lru-cache
生成的类似Map的数据结构
rewriteImports
方法
resolveImport
方法
解析node_modules
moduleResolvePlugin的作用:
- 中间件拦截/@modules/开头的ctx.path
- 若用户项目dependencies没有vue,就用vite的dependencies里的@vue
- 若moduleIdToFileMap里有id对应的文件路径,读取并返回文件
- 若预优化目录node_modules/.vite_opt_cache有id,读取并返回文件
- 都没有的话从node_modules下解析模块id里package.json的module属性对应的文件路径,读取并返回文件
*.vue文件怎么处理?
- 通过
vuePlugin
中间件来解析处理 - 使用
@vue/compiler-sfc
解析vue文件,重写成新的script以es module形式导出 - 浏览器解析后再次异步请求带有query参数的请求处理template
- 使用
@vue/compiler-dom
编译,导出render函数处理style - 借助热更新updateStyle并导出JSON字符串形式的css内容
处理后的style
文件
处理后的template
文件
解析后的结果可以直接在createApp方法中进行使用
vite.config.js
目前vite文档还没有确定具体怎么配置config文件,不过我们可以从代码中看到
大致包括proxy
、configureServer
等
HMR
当request.path 路径是 /vite/client 时、请求得到对应的客户端代码,在客户端中创建了一个websocket服务并与服务端建立了连接,通过chokidar
这个库创建watcher实例,监听文件变化,不同的消息触发一些事件做到浏览器端的即时热模块更换
一些优化
启动服务前的预优化
启动服务前,会进行预优化,把用户项目的npm依赖打包到node_module下的.vite_opt_cache目录缓存下来,这些js文件里不存在import,不用发起多次请求,利用http缓存可以提高读取node_modules里模块的加载速度
执行vite命令后直接安装npm包,无需重启服务。
先启动服务器,再安装lodash-es,跳过预优化,观察network发现有600多次请求
启动服务器前安装lodash-es,预优化后请求数明显减少
ctx.read
方法会从内存中读取已缓存文件
node_modules模块第一次解析后缓存到内存中,不用每次从磁盘中读取
http2/https
执行 vite --https
会开启http2协议,多个请求都是通过一个 TCP 连接并发完成
总结
vite在浏览器端使用 export import 的方式导入和导出模块,同时实现了按需加载。vite高度依赖module script特性。目前还是rc版本,项目还在飞速迭代中,可以自己先体验起来了。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!