vite底层实现原理

102 阅读3分钟

好问题 👍。
我给你从整体到细节把 Vite 的底层实现原理 梳理一下,分成 开发阶段构建阶段 两部分来看。


一、设计理念

Vite 的核心目标就是:开发时极快冷启动 + 按需编译
传统的 Webpack 在启动时需要 打包整个项目,Vite 则反其道而行:

  • 开发阶段 → 不打包,直接用浏览器原生的 ESM(ES Modules)。
  • 生产构建 → 用 Rollup 做一次完整打包,保证产物优化。

二、开发阶段(Dev Server)

  1. 启动 HTTP Server
    Vite 本质上就是一个基于 Node.js 的开发服务器。

    • 内部用 koa 风格的中间件系统。
    • 负责拦截请求,做文件解析和转换。
  2. 依赖预构建(Pre-Bundling)

    • esbuild(Go 编写,极快)把 第三方依赖(比如 reactvuelodash)打包成一个个 ESM 模块。

    • 这样做是因为:

      • 依赖一般是 CJS/UMD 格式,不兼容浏览器 ESM。
      • 避免一个库里有成千上万个小文件,浏览器请求太慢。
    • 预构建后的依赖存放在 node_modules/.vite 下。

  3. 源码按需编译

    • 当浏览器请求 http://localhost:5173/src/main.ts

      • Vite 拦截请求,发现是 .ts 文件 → 用 esbuild 转成 JS。
    • 当请求 .vue 文件:

      • Vite 内部调用 Vue 的 SFC 编译器 → 转成 JS 模块。
    • 当请求 CSS:

      • 转成一个 JS 模块,里面 export default 是生成的 CSS 内容,并动态插入 <style>

    👉 所以,Vite 是 “请求一个文件 → 编译一个文件 → 直接返回给浏览器”

  4. HMR(热更新机制)

    • Vite 建立了一个 WebSocket 连接

    • 当源码文件变更时:

      • Vite 只重新编译修改过的模块。
      • 通知浏览器替换对应模块,而不是刷新整个页面。
    • 速度极快,因为不用重新打整个 bundle。


三、构建阶段(Build)

  1. 调用 Rollup

    • Vite 的生产构建是基于 Rollup 的二次封装。

    • 好处:

      • Rollup 的 tree-shaking 非常强大。
      • 插件生态成熟。
  2. 分包策略

    • 默认会把 node_modules 里的依赖单独拆包(利用 Rollup 的 manualChunks)。
    • 生成 vendor.[hash].js,提升浏览器缓存利用率。
  3. 优化产物

    • 压缩(terser / esbuild)。
    • CSS 抽取成单独文件。
    • 静态资源(图片、字体)根据大小决定是内联还是生成单独文件。

四、简化理解

可以把 Vite 理解成:

  • 开发时:像一个 ESM 文件服务器,只在请求时用 esbuild/编译器做格式转换,按需返回。
  • 生产时:用 Rollup 把所有源码和依赖优化成一个高效可部署的包。

五、对比 Webpack

特性ViteWebpack
开发启动速度毫秒级(因为不用打包)秒级到分钟级
模块加载浏览器原生 ESM 按需加载先打包成一个或多个 bundle
依赖预处理esbuild 预构建Loader/Plugin 慢很多
生产构建Rollup (tree-shaking 优秀)Webpack 自身构建
热更新 (HMR)精准模块替换,极快依赖打包粒度,速度较慢

👉 总结一句话:
Vite 开发时就是一个智能的 ESM 文件服务 + 依赖预构建,构建时再用 Rollup 打包优化。