Agent Developer Roadmap
构建工具

Vite:HTML 驱动的开发服务器与 Rolldown 生产构建

核验日期:2026-07-08。示例版本来自 examples/build-tools/package.jsonvite 8.1.3。Vite 官方文档当前显示 v8.1.x,本文以 Vite 8/8.1 的 Rolldown 线为基准,同时说明 Vite 6/7 的 esbuild + Rollup 双引擎边界。

需要掌握的问题

主题读者必须回答的问题原理与边界高频错误代码或观察证据来源
Vite 双生命周期开发服务器和生产构建为什么不是同一条路径?开发时从 HTML 请求进入 module graph,按需 transformRequest 后交给浏览器 ESM;生产时以 HTML entry 进入 Rolldown graph 输出 chunks/assets/manifest用 dev 的原生 ESM 请求数推断生产 bundle;只测 vite dev 不测 vite builddev/prod Mermaid、共享 vite.config.mjsGetting Started
module graphtransformRequest浏览器请求一个模块时 Vite 做了什么?Vite server 维护 module graph;每个模块请求触发 resolve、load、transform 和 import analysis,并缓存 transform 结果把 Vite 当静态文件服务器,忽略 TS/CSS/env/import analysis 都被转换Plugin API 的 plugin container 钩子说明Plugin API
Plugin containerVite 插件为什么像 Rollup/Rolldown,又不完全等同?dev server 创建 plugin container 调用 Rolldown/Rollup 风格的 build hooks;dev 中不会调用完整输出钩子,也不会调用 moduleParsed在 dev 插件里依赖 generateBundlemoduleParsedresolveId/load/transform dev 调用表Plugin API
HMR 与 import.meta.hotVite 如何在不刷新页面时替换模块?Vite 通过 HMR 图找受影响模块,客户端用 import.meta.hot.acceptdisposeinvalidate 描述更新边界accept 写法不被静态分析识别;忘记 dispose 导致重复事件监听HMR API 最小代码与错误完整流程HMR API
env 与 secret boundaryimport.meta.env 何时替换,哪些变量能进浏览器?内置常量和 VITE_ 前缀变量在 dev 可读、build 时静态替换;值进入 bundle 后不再是秘密把数据库密码写成 VITE_DB_PASSWORD,或把字符串 env 当布尔值.env 示例和产物搜索Env Variables and Modes
base 与部署路径为什么本地打开正常,部署到子路径或 CDN 后 404?base 决定 JS、CSS、asset、HTML 引用的公共路径;./ 适合嵌入式相对部署忘记配置 /repo/、CDN origin 不一致、只测根路径示例 base: './'、Network 404 定位表Public Base Path
生产 build 与 manifest生产输出怎样被静态站点或后端模板消费?vite build<root>/index.html 为入口,Vite 8 用 Rolldown 输出优化后的 chunks/assets;build.manifest 生成 .vite/manifest.json服务端手写 hash 文件名、manifest path 拼错、旧 HTML 指向已删 assetartifact test 读取 .vite/manifest.jsonsrc/detail.tsbuild.manifest
SSR 与 Environment APISSR、custom runtime 和普通浏览器 build 的边界在哪里?Vite 6 引入 Environment 概念;Environment API 让框架/运行时映射 client、ssr、worker 等环境,但仍处 RC/实验边界在普通应用里直接依赖底层 Environment API;把 SSR build 当浏览器 buildEnvironment API 状态和 SSR manifest 边界Environment API
Vite 6/7 到 Vite 8Vite 8 为什么从 esbuild + Rollup 变成 Rolldown 统一引擎?Vite 6/7 dev 和 build 使用两套转换/打包管线;Vite 8 用 Rolldown 减少双管线差异并提升性能沿用“build 由 Rollup 驱动”的旧认知;插件只在 Vite 7 测过Vite 8 release、this.meta.rolldownVersionVite 8 release
Vite 8.1 bundled dev实验 bundled dev 解决什么,为什么不能默认启用?Vite 8.1 引入 experimental bundled dev mode,目标是大应用减少模块请求并保持 HMR;它仍有插件兼容和功能覆盖限制把实验模式当默认建议,或用它掩盖生产构建问题Vite 8.1 release 的实验性说明Vite 8.1 release
严重问题与验收怎样证明 Vite 产物能被浏览器加载,而不只是命令退出 0?检查 HTML、manifest、JS/CSS、async chunk、Source Map、base 和运行时可见副作用base 404、env leak、HMR dispose 不完整、dev 推断 prod、manifest paths 错误pnpm --filter @roadmap/build-tools-slice build:vite 和 artifact testBuilding for Production

内容边界说明:

分类本文落点
编程语言与类型系统解释 TS/JSX 只做转译、import.meta.env 静态替换和 ESM/dynamic import;不把 Vite 当类型检查器
Browser APIs 与持久化能力覆盖浏览器 ESM、HMR WebSocket、dynamic import、Source Map、HTTP/CDN/base 路径;不讨论 IndexedDB、Storage 权限模型
UI 框架与元框架说明框架插件、HMR 边界和 SSR/Environment API 接口;组件渲染、Diff、水合由框架专栏负责
构建工具与运行时完整覆盖 HTML 入口、module graph、transform、插件、HMR、env、manifest、产物和 Vite 8 迁移
后端、数据与 Agent 技术只覆盖环境变量泄露、SSR manifest、构建插件以开发者权限运行;数据库一致性和 Agent 评测不适用

Vite 的双路径:开发按请求,生产按入口

Vite 不是“Rollup 配置包装器”。它有两条生命周期:

  1. 开发路径:浏览器请求 HTML 和模块,Vite server 按需 transform,再把接近源码形态的 ESM 交给浏览器执行。
  2. 生产路径:vite build 从 HTML entry 收集依赖,用 Vite 8 的 Rolldown 生成优化后的 chunks、assets 和 manifest。

这两条路径共享插件、配置和源码,但不能互相替代验收。

问题开发路径回答生产路径回答
改一行代码后多快反馈?module graph invalidation、transform cache、HMR 边界不回答
用户下载哪些文件?不稳定,取决于浏览器请求源码模块chunks/assets/hash/manifest
base 或 CDN 是否正确?只能粗略观察必须用 build + preview/静态服务验证
Tree Shaking 是否生效?通常不是最终结果看生产 bundle 和 minify 后输出
env 是否泄露?dev 可快速观察build 后搜索产物才是最终证据

严重问题完整流程:

症状根因观察命令修正
dev 正常,部署后白屏dev server 以 root 服务源码,生产 asset path/base 不同pnpm --filter @roadmap/build-tools-slice build:vite 后静态预览 dist/vite配置 base,验证 build 输出的 HTML 和 Network
dev 请求很多就断言生产也很多开发是 unbundled ESM,生产会打包分块比较 dev Network 和 dist/vite/.vite/manifest.json用生产产物做部署和性能判断
类型错误没阻塞 ViteVite 对 TS 只做转译,不做类型证明单独跑 tsc --noEmit把类型检查放在独立脚本或 CI

开发路径:HTML 请求 → module graphtransformRequest → 浏览器 ESM → HMR

Vite 把 index.html 当源码入口,而不是放在 public/ 的静态壳。官方文档明确说明 HTML 是 module graph 的一部分,会解析 <script type="module" src="...">,也会处理 CSS 和资源 URL。

共享示例的开发入口在 examples/build-tools/src/index.html,生产配置把 root 指向 src/

export default defineConfig({
  root: fileURLToPath(new URL('../src/', import.meta.url)),
  base: './',
  build: {
    outDir: fileURLToPath(new URL('../dist/vite/', import.meta.url)),
    emptyOutDir: true,
    sourcemap: true,
    manifest: true,
    minify: 'esbuild',
    cssMinify: false,
    target: 'es2022',
  },
});

开发时的关键过程:

阶段输入Vite 处理输出
HTML 请求/index.html解析 HTML、注入 Vite client、记录 HTML 与 module graph 关系浏览器可执行的 HTML
JS/TS 请求/src/main.tstransformRequest 调插件 resolveId/load/transform,做 TS 转译和 import analysis浏览器可执行 ESM
CSS 请求或导入import './styles.css'CSS transform、URL 处理、HMR 边界<style> 注入或 CSS 模块结果
动态导入import('./detail.ts')保留浏览器 dynamic import 能力,按需 transform 目标模块点击后请求 detail 模块
文件变化changed filemodule graph invalidation,找 HMR 边界局部更新或 full reload

调试入口:

pnpm --filter @roadmap/build-tools-slice exec vite --config configs/vite.config.mjs --debug

如果只需要本仓库已验证的生产构建,运行:

pnpm --filter @roadmap/build-tools-slice build:vite

预期结果不是“开发服务器启动”,而是写出 dist/vite/ 下的生产文件。

Plugin container:像 Rolldown/Rollup,但 dev 不跑输出阶段

Vite 插件兼容 Rollup/Rolldown 风格的很多 hooks。关键差异是:开发服务器按请求 transform,不会在每个请求里构建完整 bundle。因此 dev 中不会调用完整输出钩子,官方文档也说明 dev 下不调用 moduleParsed,因为 Vite 为了性能避免完整 AST parse。

钩子dev serverproduction build用途
optionsbuildStartserver 启动时调用build 启动时调用初始化插件状态
resolveId每个相关模块请求调用构建图解析时调用alias、虚拟模块、external-like 决策
load每个请求可能调用构建读取模块时调用虚拟模块、非标准资源
transform每个请求调用,接近 transformRequest 核心每个模块构建转换TS/JSX/CSS/env/自定义转换
moduleParseddev 不调用build 中可用依赖完整 AST 的分析
renderChunk/generateBundle/writeBundledev 不调用build 输出阶段调用manifest、HTML/asset 输出处理
handleHotUpdatedev 专属build 不调用自定义 HMR invalidation

一个同时考虑 dev/build 的插件:

function buildFlagPlugin() {
  return {
    name: 'build-flag',
    resolveId(id) {
      if (id === 'virtual:build-flag') return '\0virtual:build-flag';
      return null;
    },
    load(id) {
      if (id === '\0virtual:build-flag') {
        return `export const mode = ${JSON.stringify(process.env.NODE_ENV ?? 'development')}`;
      }
      return null;
    },
    transform(code, id) {
      if (!id.endsWith('.ts')) return null;
      return { code, map: null };
    },
    generateBundle(_, bundle) {
      this.emitFile({
        type: 'asset',
        fileName: 'asset-count.json',
        source: JSON.stringify({ count: Object.keys(bundle).length }),
      });
    },
  };
}

错误完整流程:

症状根因观察命令修正
dev 下插件没生成 asset-count.jsongenerateBundle 是 build 输出钩子,dev 不调用启动 dev 后搜索内存/磁盘输出dev 逻辑放 transform/configureServer,产物逻辑放 build hooks
dev 和 build 转换结果不同插件根据 commandssrthis.meta.rolldownVersion 分支不一致打印插件 env,跑 dev/build fixture显式测试两条路径,不共用未经验证的状态
升 Vite 8 后插件边缘行为变化Vite 8 底层切到 Rolldown,兼容面很大但不是“无需回归”搜索 this.meta.rolldownVersion,跑插件集成测试插件按 Vite 8/Rolldown 重新验收,避免依赖私有行为

HMR 与 import.meta.hot:更新边界必须显式清理副作用

Vite 的 HMR 建立在原生 ESM 和 module graph 上。框架插件通常替你写好边界;手写模块时,需要明确 acceptdisposeinvalidate

let timer = setInterval(() => {
  console.log('tick');
}, 1000);

if (import.meta.hot) {
  import.meta.hot.accept((nextModule) => {
    console.log('module updated', nextModule);
  });

  import.meta.hot.dispose(() => {
    clearInterval(timer);
  });
}

重要边界:

API解决的问题不能解决
import.meta.hot.accept声明当前模块或依赖可热更新自动清理旧事件监听、旧定时器、旧全局状态
import.meta.hot.dispose在旧模块实例被替换前清理副作用证明新模块一定能无损接管所有状态
import.meta.hot.data在模块实例之间保存少量状态保存复杂应用状态或替代框架状态管理
import.meta.hot.invalidate当前模块判断无法安全热更,向上传播或刷新掩盖错误边界;必须仍有 accept 才能继续监听
handleHotUpdate插件自定义受影响模块或发送自定义事件生产构建行为

严重问题完整流程:

症状根因观察命令修正
改一次代码,点击事件触发两次dispose 没移除旧监听浏览器控制台打印 listener 次数dispose 里移除事件、定时器、订阅
accept 写了但仍 full reloadimport.meta.hot.accept( 形态没被静态分析识别,或更新越过边界看终端和浏览器 HMR 日志保持可静态分析写法,必要时接受依赖更新
HMR 正常但生产报错HMR 路径没经过 minify/chunk/base/manifest同时跑 vite build 和静态预览不用 HMR 成功替代生产验收

env、import.meta.env 和 secret boundary

Vite 暴露 import.meta.env。内置常量如 MODEDEVPRODSSRBASE_URL 总是可用。自定义变量默认只有 VITE_ 前缀会进入客户端源码。

VITE_PUBLIC_ANALYTICS_ID=demo
DB_PASSWORD=do-not-ship
console.log(import.meta.env.VITE_PUBLIC_ANALYTICS_ID); // "demo"
console.log(import.meta.env.DB_PASSWORD); // undefined

安全边界是:进入浏览器 bundle 的值不是秘密。Vite build 会静态替换这些表达式,值会永久写进 JS 文件。

变量浏览器可见性风险修正
VITE_API_BASE可见可以公开的 API 地址通常可接受明确是 public config
VITE_DB_PASSWORD可见严重泄露改为服务端 secret,不进前端构建
DB_PASSWORD默认不可见插件或自定义 define 仍可能泄露禁止把 secret 写入 define 或日志
import.meta.env.PRODbuild 时静态替换只适合分支裁剪不承载业务权限判断

错误完整流程:

症状根因观察命令修正
生产 JS 里出现密钥变量用了 VITE_ 前缀,或 define 直接注入 secret`rg "passwordsecret
if (import.meta.env.VITE_FLAG) 永远为真env 值都是字符串,"false" 也 truthy打印 build 后分支或单元测试显式比较 === "true"
SSR 和 client env 混用import.meta.env.SSR 分支没隔离跑 client build 和 SSR build分清 server-only code,不在 client import server secret

base、静态资源、hash、CDN 和 manifest

Vite 的 base 决定资源公共路径。默认是 /,部署到子路径时需要改成 /repo/;要支持任意嵌入路径时可以用 ./。共享示例使用:

export default defineConfig({
  root: fileURLToPath(new URL('../src/', import.meta.url)),
  base: './',
  build: {
    outDir: fileURLToPath(new URL('../dist/vite/', import.meta.url)),
    manifest: true,
  },
});

build.manifest: true 的预期输出路径是 .vite/manifest.json。它映射非 hash 源文件到 hash 产物,后端模板或测试可用它找正确资源。

严重问题完整流程:

症状根因观察命令修正
部署到 /docs/ 后 JS/CSS 404base 仍是 / 或 HTML 被错误移动DevTools Network 看请求是否从站点根发出设置 base: "/docs/"./,并用真实子路径预览
点击后 async chunk 404initial assets 路径正确,但 dynamic import base 错点击触发 detail,看 async JS URL同时验证初始和动态 chunk,不只看首屏
后端模板加载旧 hash没读 manifest,手写文件名或缓存旧 manifest对照 .vite/manifest.json 和 HTML每次发布同步 manifest,HTML 短缓存,assets 长缓存
CDN 上 CSS 200 但样式错CSS/asset 路径被 CDN rewrite 或 MIME 错Network Response Headers 和 CSS sourceMappingURLCDN 保留路径结构和 MIME;必要时用绝对 base

manifest 不是浏览器运行时必须文件;它是发布系统和服务端集成的契约。普通静态站点可只用 Vite 生成的 index.html,但后端模板需要 manifest 才能拿到 hash 文件名。

生产 build:HTML entry → Rolldown graph → chunks/assets → manifest

运行命令:

pnpm --filter @roadmap/build-tools-slice build:vite

Vite 8 的 production build 使用 Rolldown。共享示例的输入是 HTML:

examples/build-tools/src/index.html
examples/build-tools/src/main.ts
examples/build-tools/src/detail.ts
examples/build-tools/src/styles.css

预期结果:

examples/build-tools/dist/vite/index.html
examples/build-tools/dist/vite/.vite/manifest.json
examples/build-tools/dist/vite/assets/*.js
examples/build-tools/dist/vite/assets/*.css
examples/build-tools/dist/vite/assets/*.js.map
examples/build-tools/dist/vite/assets/*.css.map

验证观察:

find examples/build-tools/dist/vite -type f | sort
node --test --test-name-pattern vite examples/build-tools/test/artifacts.test.mjs

预期输出要点:

观察点预期结果
index.html通过相对 script type="module" 加载 initial JS,通过 stylesheet 加载 CSS
.vite/manifest.json包含 src/detail.ts,且该 entry 是 isDynamicEntry: true
JS/CSS有 hash assets 和外部 Source Map
dynamic JS不被 HTML 直接加载,而是由运行时 dynamic import 触发
bundled JS包含 Babelpreserved,不包含 SHOULD_NOT_REACH_BUNDLE

如果 vite build 退出 0,但 .vite/manifest.json 中没有 src/detail.ts dynamic entry,说明异步边界已经被错误合并、元数据丢失或测试输入不再覆盖动态导入。

SSR 与 Environment API:框架边界,不是普通应用的默认入口

Vite 支持 SSR build,也在 Vite 6 之后 formalize 了 Environment 概念。Environment API 允许框架和 runtime provider 创建 client、ssr、worker、edge 等不同环境,让 dev 更接近生产运行时。官方当前仍把 Environment API 描述为 Release Candidate,并说明部分具体 API 仍是 experimental。

边界表:

能力适用对象产物/运行时不适合
普通 client buildSPA、静态站点、前端应用浏览器 JS/CSS/assets服务端渲染入口
SSR build框架或自研 SSR 服务server bundle + client manifest/ssr manifest直接部署到纯静态 CDN
Environment API框架作者、runtime provider、复杂插件多环境 dev/build 抽象普通业务应用随手接入底层 API
vite preview本地预览生产 build静态预览服务器生产服务器

错误完整流程:

症状根因观察命令修正
SSR 里访问 window 崩溃server environment 执行了 browser-only codeimport.meta.env.SSR 分支和 SSR build 日志拆分 client-only import,或动态导入到客户端
普通应用直接使用 Environment API 后升级困难依赖 RC/experimental 低层接口检查 Vite 版本和 API changelog优先使用框架集成;低层 API 留给框架/插件层
SSR manifest 缺 CSS只构建 server,没有合并 client assets检查 build.ssrManifest 和 client manifest按框架文档同时构建 client/server 并合并

Vite 6/7 到 Vite 8:重大变化是 Rolldown 统一引擎

Vite 6/7 的常见认知是:dev 侧用 esbuild 做依赖预构建和快速转译,build 侧用 Rollup 输出生产 bundle。这套双引擎长期有效,但也带来两套插件系统和边缘语义对齐成本。

Vite 8 的重大变化是使用 Rolldown 作为底层构建引擎,并让 Vite 插件生态围绕同一方向收敛。官方 Vite 8 发布说明强调 Rolldown 的目标包括性能、兼容 Rollup/Vite 插件 API,以及统一引擎带来的高级能力。

维度Vite 6/7Vite 8
生产构建底层RollupRolldown
转换/打包心智模型esbuild + Rollup 双管线Rolldown 统一管线为核心
插件兼容Rollup 风格 + Vite 特定 hooks继续兼容大多数 Vite 插件,但需回归边缘行为
检测方式没有 Rolldown meta插件可读 this.meta.rolldownVersion
性能结论取决于项目、插件和缓存官方报告多家公司 build time 降低,但本文不把它外推到所有项目

迁移严重问题完整流程:

症状根因观察命令修正
Vite 7 插件在 Vite 8 build 输出不同插件依赖 Rollup 私有细节或输出 hook 边缘行为跑插件 fixture,检查 this.meta.rolldownVersion用公开 API,针对 Vite 8/Rolldown 做回归
团队文档仍写“Vite build 等于 Rollup build”认知停留在 Vite 7查看 vite --version 和官方 release更新构建边界说明,避免排查走错文档
性能升级不明显项目瓶颈在框架插件、类型检查、CSS 或 I/Obenchmark 分开统计 transform/build/typecheck拆分瓶颈,不把 Rolldown 当万能加速器

Vite 8.1 experimental bundled dev:只作为大应用实验选项

Vite 8.1 引入 experimental bundled dev mode。官方说明它以前叫 Full Bundle Mode,目标是改善超大应用因模块数量过多导致的启动和 full reload 成本,同时保持 HMR 高效。官方也给出初步测试和真实应用反馈。

但它是实验能力,不是默认建议。原因很直接:

风险说明决策
插件兼容dev 从 unbundled 转为 bundled,会改变插件观察到的请求模型和边界只在插件兼容测试通过后试用
功能覆盖实验模式可能尚未覆盖所有 Vite dev 特性不作为基础教程默认路径
问题定位bundled dev 更接近生产,但也更难直接观察单源码模块请求保留普通 dev 作为对照结果
性能外推官方数字来自特定大应用和测试条件本地 benchmark 要写清源码规模、机器、插件和缓存状态

适用判断:

场景是否考虑
几百个模块的小应用通常不需要,默认 dev 更简单
上万模块、首屏请求和 full reload 明显拖慢可开实验分支测试 bundled dev
插件大量依赖 dev 请求粒度先不启用,除非插件作者明确支持
生产构建失败bundled dev 不是修复手段,先修 build

严重问题完整流程:

症状根因观察命令修正
bundled dev 下某插件不生效插件依赖 unbundled dev 的模块请求粒度对比普通 dev 和 bundled dev 的插件日志保持默认 dev,向插件维护者反馈或等待覆盖
启用后 HMR 边界变粗打包后的模块归组改变更新传播浏览器 HMR 日志和状态保留情况缩小实验范围,保留 full reload 回退
团队把实验模式写进模板默认值未验证插件、框架和调试成本新项目 smoke test + 插件兼容测试默认仍用普通 dev,仅大项目 opt-in

共享示例:Vite 构建 HTML 应用入口

运行命令:

pnpm --filter @roadmap/build-tools-slice build:vite

输入:

examples/build-tools/src/index.html
examples/build-tools/src/main.ts
examples/build-tools/src/catalog.ts
examples/build-tools/src/detail.ts
examples/build-tools/src/side-effect.ts
examples/build-tools/src/styles.css

预期结果:

examples/build-tools/dist/vite/index.html
examples/build-tools/dist/vite/.vite/manifest.json
examples/build-tools/dist/vite/assets/*.js
examples/build-tools/dist/vite/assets/*.css
examples/build-tools/dist/vite/assets/*.js.map
examples/build-tools/dist/vite/assets/*.css.map

本仓库还补了一个 css-source-maps build 插件,因为当前示例需要外部 CSS map 作为统一 artifact 证据:

function cssSourceMaps() {
  return {
    name: 'css-source-maps',
    apply: 'build',
    generateBundle(_options, bundle) {
      for (const asset of Object.values(bundle)) {
        if (asset.type !== 'asset' || !asset.fileName.endsWith('.css')) continue;
        this.emitFile({
          type: 'asset',
          fileName: `${asset.fileName}.map`,
          source: JSON.stringify({
            version: 3,
            sources: ['../../../src/styles.css'],
            names: [],
            mappings: '...',
          }),
        });
      }
    },
  };
}

这段插件只服务示例验收,不代表所有项目都要手写 CSS map 插件。真实项目按错误平台、源码保密和浏览器调试策略选择 external、hidden 或不发布 Source Map。

验证观察:

观察点预期结果
index.html不包含工作区绝对路径,不直接加载 async detail chunk
.vite/manifest.jsonsrc/detail.ts 对应 dynamic entry
JS source map主 chunk 指回 main.ts,async chunk 指回 detail.ts
CSS source mapsources 是相对路径并指向真实 styles.css
bundled JS包含 Babelpreserved,不包含 SHOULD_NOT_REACH_BUNDLE

严重问题总表:不要用“能启动”替代验收

严重问题表现根因最小观察修正
base 404首屏或点击后 JS/CSS 404base 与部署子路径/CDN 不一致DevTools Network、构建后静态预览设置正确 base,同时验证 initial 和 async chunk
env leak产物包含密码、token 或内部 URL使用 VITE_define 注入 secret`rg "secretpassword
HMR dispose 不完整更新后重复事件、重复定时器、状态污染旧模块副作用未清理控制台计数、HMR 日志dispose 清理监听、订阅、timer
用 dev 推断 proddev 正常但 build 失败或白屏dev 和 build 路径不同必跑 vite build 和静态预览生产验收以 build 产物为准
manifest paths 错误后端模板加载不存在 hash 文件manifest 路径拼接错或旧 manifest对照 .vite/manifest.json 与 dist 文件发布同步 manifest,模板只读 manifest
Source Map 泄露.map 暴露源码和本机路径发布 external map 无过滤`rg "$PWDfile:" dist/vite`

资料入口

在 GitHub 上编辑此页

本页目录