web-tooling-vite
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVite Patterns
Vite 模式
Quick Guide: Vite serves unbundled ES modules in development and bundles for production, so most configuration decisions apply to only one of those halves. The version decides the API: Vite 8 bundles with Rolldown (,build.rolldownOptions,codeSplitting.groups), Vite 7 with Rollup (resolve.tsconfigPaths,build.rollupOptions, aliases mirrored intomanualChunksby hand). Sass runs on the modern API from Vite 6 onwards, and the legacy API is gone from Vite 7.tsconfig.json
Detailed Resources:
- examples/core.md — full configs for aliases, chunk splitting, environment-specific builds, module preload, Sass, the Environment API and the dev proxy
- reference.md — dev/production settings, build-target table, per-version notes and the Vite 8 migration checklist
快速指南: Vite 在开发环境中提供未打包的 ES modules,并在生产环境中进行打包,因此大多数配置决策只适用于这两个阶段中的一个。版本决定所使用的 API:Vite 8 使用 Rolldown 打包(、build.rolldownOptions、codeSplitting.groups),Vite 7 使用 Rollup(resolve.tsconfigPaths、build.rollupOptions,别名需手动同步到manualChunks)。从 Vite 6 开始,Sass 使用 modern API;Vite 7 已移除 legacy API。tsconfig.json
详细资源:
- examples/core.md——别名、chunk 拆分、分环境构建、module preload、Sass、Environment API 和开发代理的完整配置
- reference.md——开发/生产设置、build target 对照表、各版本注意事项和 Vite 8 迁移检查清单
Which path applies
应采用哪条路径
Read the version in before writing config; the two branches share names and not behaviour.
vitepackage.json- Vite 8 (Rolldown) — ,
build.rolldownOptionsfor chunking,codeSplitting.groupsinstead of hand-mirrored aliases.resolve.tsconfigPathsstill resolves as a deprecated alias, which is why a wrong-version config looks like it works.build.rollupOptions - Vite 7 (Rollup) — with
build.rollupOptions, and aliases declared in bothmanualChunksandvite.config.ts.tsconfig.json
<critical_requirements>
在编写配置前,先查看 中的 版本;这两个分支虽然名称相同,但行为不同。
package.jsonvite- Vite 8(Rolldown)——使用 ,通过
build.rolldownOptions进行 chunk 拆分,并使用codeSplitting.groups,而不是手动同步别名。resolve.tsconfigPaths仍可解析,但它是 deprecated alias,因此错误版本的配置看起来也能正常工作。build.rollupOptions - Vite 7(Rollup)——使用带有 的
manualChunks,并在build.rollupOptions和vite.config.ts中同时声明别名。tsconfig.json
<critical_requirements>
Before writing Vite config
编写 Vite 配置前
Declare path aliases in one place per version — on Vite 8, or the same set in both and on Vite 7. A pair that has drifted resolves in one tool and not the other, so the build and the editor disagree about the same import.
resolve.tsconfigPathsvite.config.tstsconfig.jsonMatch the bundler options to the version. On Vite 8 that is with ; object-form is removed there and silently produces no grouping.
build.rolldownOptionscodeSplitting.groupsmanualChunksSplit config by mode rather than shipping one build. with keeps minification and sourcemaps out of development and out of the production bundle respectively.
defineConfig(({ mode }) => …)loadEnvReach for , the current spelling — is deprecated and offers no control over which dependencies are preloaded.
build.modulePreload.polyfillbuild.polyfillModulePreload</critical_requirements>
Auto-detection: Vite, vite.config.ts, vite.config.js, defineConfig, loadEnv, manualChunks, advancedChunks, codeSplitting.groups, rolldownOptions, rollupOptions, modulePreload, resolve.alias, resolve.tsconfigPaths, build.target, baseline-widely-available, VITE_
Applies to:
- Configuring a Vite build for a frontend application
- Path aliases, and keeping them resolvable by both the bundler and the type checker
- Vendor chunk splitting for cacheable production output
- Per-mode builds (development, staging, production) with and
loadEnvdefine - Migrating a config from Vite 7 to Vite 8
- Module preload, build targets and Sass preprocessing
Handled elsewhere:
- Compiler options and type-checking behaviour, beyond the entry an alias needs
paths - Lint and format configuration
- Application code that runs in the browser — this is build-time configuration only
- Build orchestration by an SSR meta-framework, which owns its own config file
- Pipeline and deployment concerns around the build command
<philosophy>
Development and production run different machinery. The dev server transforms modules on demand and ships them unbundled, so nothing there is tree-shaken, minified or chunked; the production build is a bundler run with all three. Every defect that survives to release lives in that gap — a stylesheet dropped by tree-shaking, a chunk that only exists in production, an env var that was present locally.
So the useful question about any option is which half it governs, and whether the other half will ever exercise it.
</philosophy>
<decision_framework>
每个版本只在一处声明 path aliases——Vite 8 使用 ,Vite 7 则在 和 中声明同一组别名。如果两处配置发生偏差,解析结果就会在工具之间不一致,导致 build 和 editor 对同一 import 的解析结论不同。
resolve.tsconfigPathsvite.config.tstsconfig.json使 bundler options 与版本匹配。 Vite 8 使用带有 的 ;对象形式的 在该版本中已被移除,并且会悄无声息地导致不进行任何分组。
codeSplitting.groupsbuild.rolldownOptionsmanualChunks按 mode 拆分配置,而不是始终交付同一种 build。 使用带有 的 ,可以确保 development 不进行压缩,并确保 production bundle 不包含 sourcemap。
loadEnvdefineConfig(({ mode }) => …)使用 ,这是当前拼写方式; 已弃用,而且无法控制要预加载哪些依赖项。
build.modulePreload.polyfillbuild.polyfillModulePreload</critical_requirements>
自动检测: Vite、vite.config.ts、vite.config.js、defineConfig、loadEnv、manualChunks、advancedChunks、codeSplitting.groups、rolldownOptions、rollupOptions、modulePreload、resolve.alias、resolve.tsconfigPaths、build.target、baseline-widely-available、VITE_
适用于:
- 为前端应用配置 Vite build
- 路径别名,以及确保 bundler 和类型检查器都能解析这些别名
- 拆分 vendor chunk,以生成可缓存的生产环境产物
- 使用 和
loadEnv按 mode 构建(development、staging、production)define - 将配置从 Vite 7 迁移到 Vite 8
- Module preload、build target 和 Sass 预处理
不在此处处理:
- 编译器选项和类型检查行为,但不包括 alias 所需的 条目
paths - Lint 和格式化配置
- 在浏览器中运行的应用代码——本文仅涉及构建时配置
- SSR meta-framework 执行的构建编排,因为它拥有自己的配置文件
- 围绕 build command 的 pipeline 和 deployment 事项
<philosophy>
开发和生产运行着不同机制。dev server 按需转换 modules,并以未打包的形式提供,因此其中不会进行 tree-shaking、压缩或 chunk 拆分;production build 则由 bundler 执行这三项。所有遗留到发布阶段的缺陷都源于这种差异——被 tree-shaking 丢弃的 stylesheet、仅在 production 中存在的 chunk,或仅在本地存在的环境变量。
因此,评估任何选项时,真正有用的问题是:它控制哪一半,以及另一半是否会在任何时候用到它。
</philosophy>
<decision_framework>
Chunk splitting
Chunk 拆分
Vite 8 (Rolldown)?
├─ Separating vendors by package → codeSplitting.groups with a test regex ✓
└─ Constraining by size or share count → codeSplitting maxSize / minSize / minShareCount
Vite 7 (Rollup)?
├─ Separating vendors by package → manualChunks, object form ✓
└─ Logic per module id → manualChunks, function formadvancedChunkscodeSplittingVite 8 (Rolldown)?
├─ 按依赖包分离 vendor → 使用 codeSplitting.groups 和 test regex ✓
└─ 按大小或共享数量限制 → codeSplitting maxSize / minSize / minShareCount
Vite 7 (Rollup)?
├─ 按依赖包分离 vendor → manualChunks,对象形式 ✓
└─ 按 module id 划分逻辑 → manualChunks,函数形式advancedChunkscodeSplittingBuild target
Build target
Are there browsers below the default floor to support?
├─ YES → @vitejs/plugin-legacy alongside the modern build
└─ NO → Smallest possible output?
├─ YES → 'esnext'
└─ NO → 'baseline-widely-available' (the default) ✓, or an explicit list
such as ['chrome111', 'safari16.4'] when a contract names versions</decision_framework>
<patterns>
需要支持低于默认下限的浏览器吗?
├─ 是 → 在 modern build 旁使用 @vitejs/plugin-legacy
└─ 否 → 需要尽可能小的输出?
├─ 是 → 'esnext'
└─ 否 → 'baseline-widely-available'(默认值)✓,或在合同时指定版本时
显式列出,例如 ['chrome111', 'safari16.4']</decision_framework>
<patterns>
Core patterns
核心模式
Pattern 1: Path Aliases
模式 1:路径别名
One alias set, resolvable by the bundler and the type checker alike.
typescript
// Vite 8 — read straight from tsconfig.json
resolve: { tsconfigPaths: true },
// Vite 7 — declared here and mirrored in tsconfig.json "paths"
resolve: {
alias: { "@": path.resolve(__dirname, "./src") },
},resolve.tsconfigPathspathstsconfig.jsonpathsresolve.aliasFull code: examples/core.md
使用同一组别名,并确保 bundler 和类型检查器都能解析。
typescript
// Vite 8 — read straight from tsconfig.json
resolve: { tsconfigPaths: true },
// Vite 7 — declared here and mirrored in tsconfig.json "paths"
resolve: {
alias: { "@": path.resolve(__dirname, "./src") },
},resolve.tsconfigPathspathstsconfig.jsonpathsresolve.alias完整代码:examples/core.md
Pattern 2: Vendor Chunk Splitting
模式 2:Vendor chunk 拆分
Dependencies change on a slower cadence than application code, so a separate chunk stays in the browser cache across deploys.
typescript
// Vite 8
build: {
rolldownOptions: {
output: {
codeSplitting: {
groups: [{ name: "vendor", test: /[\\/]node_modules[\\/]/ }],
},
},
},
},Narrow the per group where different dependencies move at different rates; one chunk holding everything is invalidated by any upgrade.
testFull code, including the Vite 7 form: examples/core.md
依赖项的变更频率低于应用代码,因此单独分出的 chunk 能在多次部署之间保留于浏览器缓存中。
typescript
// Vite 8
build: {
rolldownOptions: {
output: {
codeSplitting: {
groups: [{ name: "vendor", test: /[\\/]node_modules[\\/]/ }],
},
},
},
},当不同依赖项的更新频率不同时,应为每个 group 收窄 ;将所有内容放在一个 chunk 中,会因任意一次升级而失效。
test包含 Vite 7 形式在内的完整代码:examples/core.md
Pattern 3: Per-Mode Builds
模式 3:分 mode 构建
defineConfig--modetypescript
export default defineConfig(({ mode }) => ({
build: {
sourcemap: mode !== "production",
minify: mode === "production",
},
}));.env--modeNODE_ENVloadEnv(mode, cwd, "")defineFull code: examples/core.md
defineConfig--modetypescript
export default defineConfig(({ mode }) => ({
build: {
sourcemap: mode !== "production",
minify: mode === "production",
},
}));.env--modeNODE_ENVloadEnv(mode, cwd, "")define完整代码:examples/core.md
Pattern 4: Module Preload
模式 4:Module preload
typescript
build: {
modulePreload: {
polyfill: false,
resolveDependencies: (filename, deps) =>
deps.filter((dep) => !dep.includes("rarely-used-vendor")),
},
},Dropping the polyfill is safe only where the target floor supports module preload natively; is how a large chunk is kept out of the initial preload list.
resolveDependenciesFull code: examples/core.md
typescript
build: {
modulePreload: {
polyfill: false,
resolveDependencies: (filename, deps) =>
deps.filter((dep) => !dep.includes("rarely-used-vendor")),
},
},只有当目标浏览器下限原生支持 module preload 时,移除 polyfill 才是安全的; 可以将大型 chunk 排除在初始 preload 列表之外。
resolveDependencies完整代码:examples/core.md
Pattern 5: Sass
模式 5:Sass
typescript
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "./src/styles/variables" as *;`,
},
},
},The modern API is the default from Vite 6 and the only one from Vite 7, so a config still passing fails rather than falling back. Migrating means becoming / with namespaced access.
api: "legacy"@import@use@forwardtypescript
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "./src/styles/variables" as *;`,
},
},
},modern API 从 Vite 6 开始就是默认选项,并且是 Vite 7 的唯一选项,因此仍传入 的配置会直接失败,而不会回退。迁移意味着将 改为 /,并使用命名空间方式访问。
api: "legacy"@import@use@forwardPattern 6: Dev Server Proxy
模式 6:Dev server 代理
typescript
server: {
proxy: {
"/api": { target: "http://localhost:8000", changeOrigin: true },
},
},Proxying keeps development same-origin, so no CORS configuration is needed for a backend that will be same-origin in production anyway.
typescript
server: {
proxy: {
"/api": { target: "http://localhost:8000", changeOrigin: true },
},
},使用代理可以让开发环境保持同源,因此对于生产环境中也将同源的后端,无需配置 CORS。
Pattern 7: Environment API
模式 7:Environment API
For framework authors and multi-runtime builds; still RC as of Vite 8, and an ordinary single-client app needs none of it.
typescript
environments: {
client: { build: { outDir: "dist/client" } },
ssr: { build: { outDir: "dist/server", ssr: true } },
},Full code: examples/core.md
</patterns>
<red_flags>
面向 framework 作者和多 runtime 构建;截至 Vite 8,该 API 仍处于 RC 阶段,普通单客户端应用不需要使用它。
typescript
environments: {
client: { build: { outDir: "dist/client" } },
ssr: { build: { outDir: "dist/server", ssr: true } },
},完整代码:examples/core.md
</patterns>
<red_flags>
Red flags
危险信号
Breaks at runtime:
- Object-form on Vite 8 — removed, so the grouping silently does not happen and the vendor chunk you expected is not in
manualChunksdist - , removed in Vite 7 — the import throws before the build starts
splitVendorChunkPlugin - , removed in Vite 7 — replaced by
target: 'modules''baseline-widely-available' - Sass on Vite 7 or later — the legacy API is gone rather than deprecated
api: "legacy" - An alias present in and missing from
vite.config.ts, or the reverse — the build succeeds and the type check fails, or the editor resolves an import the bundler cannottsconfig.json
Surprising behaviour:
- still resolves on Vite 8 as a deprecated alias, so a Vite 7 config appears to work until a Rolldown-only option is needed
build.rollupOptions - is off by default; enabling it is a deliberate step, not a fallback
resolve.tsconfigPaths - Rolldown emits an extra chunk beside the code-split groups
runtime.js - loads every variable in the file, prefix or not — inlining one of those through
loadEnv(mode, cwd, "")publishes it in the bundledefine - is a no-op on Vite 8, since Rolldown handles CommonJS natively
build.commonjsOptions - The option auto-converts to
esbuildon Vite 8, quietly dropping the options Oxc has no equivalent foroxc - Sourcemaps left on in production ship readable source; keeps them for error reporting without linking them from the bundle
'hidden'
</red_flags>
会导致运行时故障:
- Vite 8 中的对象形式 ——该形式已被移除,因此分组会悄无声息地不发生,预期中的 vendor chunk 不会出现在
manualChunks中dist - ,Vite 7 中已移除——import 会在 build 开始前抛出错误
splitVendorChunkPlugin - ,Vite 7 中已移除——已由
target: 'modules'取代'baseline-widely-available' - Vite 7 及更高版本中的 Sass ——legacy API 已被彻底移除,而不只是弃用
api: "legacy" - alias 存在于 中却缺失于
vite.config.ts,或情况相反——build 会成功,但类型检查失败;或者 editor 能解析某个 import,而 bundler 无法解析tsconfig.json
令人意外的行为:
- 在 Vite 8 中仍可解析,但它是 deprecated alias,因此 Vite 7 配置会一直看似正常,直到需要使用仅 Rolldown 支持的选项
build.rollupOptions - 默认关闭;启用它是一个明确步骤,而不是 fallback
resolve.tsconfigPaths - Rolldown 会在 code-split groups 旁额外生成一个 chunk
runtime.js - 会加载文件中的所有变量,无论是否具有前缀——通过
loadEnv(mode, cwd, "")内联其中某个变量会将其发布到 bundle 中define - 在 Vite 8 中不起作用,因为 Rolldown 原生处理 CommonJS
build.commonjsOptions - Vite 8 中的 选项会自动转换为
esbuild,并悄悄丢弃 Oxc 没有对应实现的选项oxc - 在 production 中保留 sourcemap 会发布可读的源代码;会保留 sourcemap 以供错误报告使用,但不会从 bundle 中链接到它们
'hidden'
</red_flags>