vite 的按需编译是浏览器请求触发单文件实时转译,依赖预构建+esm原生支持实现毫秒级热更新。它不打包,只拦截 import 请求做即时转换,本质是智能静态服务+运行时转码器。

Vite 的按需编译不是“等你改完再批量处理”,而是“浏览器一要,它立刻编译一个”。核心就一句话:它把打包这件事,交给了浏览器的 import 行为来触发。
浏览器发起请求,Vite 才开始干活
你打开 http://localhost:5173,浏览器加载 index.html,遇到这行:
浏览器就会向 Vite 开发服务器发起对 /src/main.js 的请求。这时 Vite 才启动编译——只编译这一个文件,转成浏览器能直接执行的 ESM 格式,立刻返回。
接着,main.js 里写了 import { createApp } from 'vue',浏览器又去请求 vue。Vite 不会现场编译 Vue 源码,而是提前(启动时)用 esbuild 把 node_modules 里的依赖预构建好,存在缓存里,直接返回已优化的 ESM 版本。
- 所有源码(
.ts、.vue、.jsx)都不打包,只在被请求时单文件转换 - 第三方依赖不走实时编译,靠预构建加速,用 Go 写的
esbuild实现毫秒级处理 - 没有“入口分析→依赖遍历→生成 chunk”的打包流程,整个开发服务器本质是个智能静态文件服务 + 实时转码器
模块边界就是编译边界
Vite 不解析整个项目 AST,只看每个文件的 import 和 export 语句,建立轻量导入关系图。这个图决定了两件事:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 哪个文件该被编译:只有被 import 链路实际到达的文件,才会被请求、被编译
- 哪个文件需要重编译:改了
utils.js,只重新编译它自己;如果App.vue显式调用了import.meta.hot.accept('./utils.js', ...),那App.vue就不会重执行,只更新utils.js导出的内容
没有显式 accept?那就顺着 import 链向上冒泡,直到遇到接受者或回到 HTML 入口,才整页刷新。
服务端和客户端配合完成热更新
你保存一个 .vue 文件,文件系统监听到变更,Vite 做三件事:
- 对这个文件做一次独立编译,得到新的 JS 模块字符串
- 查导入关系图,算出哪些模块要收到更新(比如它的直接引用者)
- 通过 WebSocket 推送 update 消息,客户端拿到后,用带时间戳的 URL 重新 GET 这个模块,然后 patch 进当前运行时
整个过程不涉及任何 bundler 参与,没有 chunk 重建、没有依赖图全量重算,只是单文件编译 + 精准替换。
为什么不用打包,还能跑起来
因为现代浏览器(Chrome/Firefox/Safari/Edge)早已原生支持 import 加载本地路径、支持 import.meta、支持动态 import()。Vite 没有发明新机制,只是把浏览器本来就有的能力串了起来:
-
type="module"让浏览器按 ESM 规则解析脚本 - 浏览器自动发起对每个
import路径的 HTTP 请求 - Vite 拦截这些请求,实时注入转换逻辑(比如把
<script setup></script>编译成 JS)、加上import.meta.hot支持
换句话说,Vite 的开发服务器不是“提供打包结果”,而是“提供可运行的源码”——只是这些源码在传输途中被悄悄转义了一下。










