vite核心原理

Vite 在开发环境生产环境中采用了完全不同的打包策略,这是其高性能的核心设计之一。


🌐 1. 开发环境(Development):按需动态编译,不打包

✅ 核心机制:基于原生 ESM 的服务器

  • 不进行完整打包
  • 启动时仅启动一个轻量级 HTTP 服务器(基于 connect
  • 利用浏览器对 <script type="module"> 的原生支持,按需加载模块

🔧 工作流程:

  1. 浏览器请求 index.html
  2. HTML 中的 import /src/main.js 触发模块加载
  3. Vite 服务器拦截每个模块请求(如 /src/utils.js
  4. 动态编译该文件(例如:TS → JS、Vue → JS)
  5. 返回编译后的 JavaScript 内容

⚙️ 关键优化点:

步骤 技术实现
依赖预构建 使用 esbuildnode_modules 文件夹中原本不被浏览器直接支持的 CommonJS 或 UMD 格式的第三方库,自动转换成现代浏览器可以原生加载的 ES 模块(ESM)格式
按需转换 只有被访问的文件才编译,未使用的代码不会参与构建
HMR 热更新 通过 WebSocket 监听文件变化,精确替换模块,无需刷新页面

💡 举例:import _ from 'lodash' → 被重写为 /@modules/lodash.js → 由 esbuild 预构建后提供 ESM 版本

vite dev运行原理:

  1. 扫描你的代码中所有来自 node_modules 的导入(如 import _ from 'lodash'
  2. 收集需要预构建的依赖列表
  3. 使用 esbuild 将它们转换为 ESM 并打包成单个文件

HMR 热更新原理:

1. 启动服务器并建立 WebSocket 连接

  • Vite 开发服务器启动时,同时开启一个 WebSocket 服务(如 ws://localhost:24678
  • 浏览器通过注入的客户端脚本自动连接:
ini 复制代码
js
const ws = new WebSocket(`ws://localhost:${port}`);

2. 监听文件变化(使用 chokidar

  • 服务器监听项目根目录下的所有源码文件
  • 当你保存修改(如 src/utils.js),立即触发 change 事件

3. 分析模块依赖图谱

  • Vite 维护了模块之间的导入关系(Module Graph)
  • 知道哪些模块引用了被修改的文件
  • 例如:main.js → imports → utils.js,修改 utils.js 就会影响 main.js

4. 发送更新消息到浏览器

  • 服务器通过 WebSocket 推送更新通知:
json 复制代码
json
{
  "type": "update",
  "updates": [
    {
      "type": "js-update",
      "path": "/src/utils.js",
      "timestamp": 1734567890123
    }
  ]
}

5. 拉取最新模块代码

  • 浏览器接收到消息后,用时间戳作为缓存破坏参数,重新请求模块:
csharp 复制代码
js
await import('/src/utils.js?t=1734567890123');
  • 服务器返回编译后的最新 JavaScript 内容

6. 替换旧模块并更新视图

  • 执行新模块代码

  • 框架层处理更新:

    • Vue :通过 import.meta.hot.accept() 触发组件重新渲染
    • React:结合 Fast Refresh 保留状态并更新组件
    • CSS :替换 <style> 标签内容,无需重载页面

📦 2. 生产环境(Production):使用 Rollup 打包

虽然开发时不打包,但在生产环境中 Vite 会进行完整的打包优化

✅ 构建命令:

复制代码
bash
vite build

🛠️ 底层工具:Rollup

  • Vite 的生产构建是基于 Rollup 实现的
  • Rollup 更适合库和应用的静态分析与 tree-shaking
  • 支持代码分割、懒加载、CSS 提取等高级功能

📈 输出结果:

优化项 说明
Tree Shaking 删除未使用的代码
Code Splitting 自动拆分 chunk,支持动态导入
Minification 使用 Terser 压缩 JS,CSSNano 压缩 CSS
Asset Hashing 添加 content hash 实现缓存失效
Gzip/Brotli 预警 可配合插件生成压缩版本

🆚 对比总结

特性 开发环境(Dev) 生产环境(Build)
是否打包 ❌ 不打包 ✅ 完整打包
构建工具 esbuild(预构建依赖)+ 原生 ESM Rollup
启动速度 极快(毫秒级) 较慢(取决于项目大小)
模块处理 按需动态编译 全量静态分析
输出产物 无 bundle,直接服务源码 dist/ 目录包含优化后的静态资源
HMR 支持 ✅ WebSocket 实现热更新 ❌ 静态文件,不支持 HMR
适用场景 快速开发调试 部署上线

🧩 示例配置:vite.config.js

php 复制代码
js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  // 开发服务器配置
  server: {
    port: 3000,
    open: true
  },
  // 生产构建配置
  build: {
    outDir: 'dist',
    minify: 'terser',
    sourcemap: false,
    rollupOptions: {
      output: {
        chunkFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
      }
    }
  }
});

✅ 总结

  • 开发阶段:Vite 利用现代浏览器的 ESM 能力,做到"零打包",极大提升启动和热更新速度。
  • 生产阶段:切换到 Rollup 进行专业级打包,确保输出高度优化、体积小、性能好。
相关推荐
斜向生3 小时前
【JavaScript正则表达式指南】——正则表达式入门:创建、方法与标志详解
前端
朕的剑还未配妥3 小时前
Vue2函数式组件实战:手写可调用的动态组件,适用于toast轻提示、tip提示、dialog弹窗等
前端
这可不简单3 小时前
前端性能优化:从浏览器渲染原理到实战(告别 “知其然不知其所以然”)
前端·css·面试
前端开发爱好者3 小时前
尤雨溪宣布:Vite 纪录片震撼发布!
前端·javascript·vue.js
北城以北88883 小时前
ES6(二)
前端·javascript·es6
朕的剑还未配妥3 小时前
移动端触摸事件与鼠标事件的触发机制详解
前端
墨鱼鱼4 小时前
【征文计划】Rokid JSAR 实践指南:打造沉浸式 "声动空间盒" 交互体验
前端
中昊芯英4 小时前
DeepSeek-V3.2的DSA稀疏注意力技术:在TPU平台上的效能革命与适配实践
架构
携欢4 小时前
Portswigger靶场之Exploiting a mass assignment vulnerability通关秘籍
前端·安全