跳到主要内容

Vite、Webpack 与现代构建链路

📦 构建工具负责把源码、依赖和静态资源转换为浏览器可高效加载、适合部署并便于调试的产物。

现代构建链路

典型阶段:

  1. 读取配置与环境变量
  2. 解析模块入口和依赖图
  3. 转译 TypeScript / JSX / 新语法
  4. 处理 CSS、图片和其他资源
  5. Tree Shaking、代码分割与压缩
  6. 生成 sourcemap、hash 文件名和资源清单
  7. 开发服务器提供 HMR

Vite 的核心思路

开发环境利用浏览器原生 ESM,按需转换源码;依赖通常预构建以减少请求数量和兼容 CommonJS。生产构建使用 Rollup 生态完成打包与优化。

优势:

  • 冷启动快
  • 按需编译
  • HMR 粒度细
  • 配置简洁,适合现代浏览器项目

Webpack 的核心思路

Webpack 从入口构建完整依赖图,通过 loader 转换不同模块,通过 plugin 介入编译生命周期,再生成 bundle 和 chunk。

适合场景:

  • 大型遗留工程
  • 高度定制的资源处理链
  • 已沉淀丰富 loader / plugin 的项目
  • 需要精细控制模块联邦等复杂架构

关键概念对照

概念Vite / RollupWebpack
转换Plugin transformLoader
生命周期扩展Plugin hooksPlugin + compiler hooks
开发模式原生 ESM 按需转换通常先构建依赖图
生产打包RollupWebpack 自身
代码分割动态 import / manualChunks动态 import / splitChunks

Tree Shaking

Tree Shaking 依赖静态 ESM 结构。要点:

  • 使用 import / export
  • 避免顶层不可分析副作用。
  • 库通过 sideEffects 标注副作用文件。
  • Babel / TypeScript 不应过早把 ESM 转为 CommonJS。
const Editor = () => import('./Editor')

动态 import() 会形成异步 chunk,但拆得过细也会增加请求和调度成本。

缓存策略

  • 文件名使用内容 hash。
  • HTML 通常短缓存或协商缓存。
  • 带 hash 的静态资源使用长期不可变缓存。
  • 运行时环境配置不要错误地固化进需要跨环境复用的 bundle。

环境变量与安全

前端环境变量最终可能进入客户端代码,不得保存密钥。Vite 的 import.meta.env 与 Webpack 的 DefinePlugin 本质上都是构建期替换。

常见问题

  • 包中混合 ESM / CJS 导致默认导入差异。
  • monorepo 中重复依赖或 symlink 解析不一致。
  • sourcemap 泄露源码或未正确上传监控平台。
  • chunk 拆分策略导致首屏 waterfall。
  • HMR 正常但生产构建路径、base URL 或动态资源失败。

优化步骤

  1. 用可视化分析工具查看产物组成。
  2. 找出重复依赖和超大模块。
  3. 对重型、低频功能做路由或组件级懒加载。
  4. 验证压缩、缓存和 CDN 配置。
  5. 比较真实页面指标,而不仅是 bundle 大小。

工程检查清单

  • 开发、测试、生产配置边界清晰
  • 构建产物可复现
  • sourcemap 策略与错误监控一致
  • 长期缓存与版本回滚可用
  • CI 中执行类型检查、测试和构建验证