用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/aaione/everything-claude-code-zh --skill vite-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Kubernetes 工作负载模式、资源管理、RBAC、probes、autoscaling、ConfigMap/Secret 处理,以及面向生产级部署的 kubectl 调试。
完成任何非平凡任务后使用。智能体按 5 个维度自评输出——准确性、完整性、清晰度、可执行性、简洁性——每项都给出具体证据。生成结构化 1-5 评分卡和具体改进建议。
在 competitive-platform-analysis 产出分层竞品集合后使用。按九个加权维度(定位、声音、视觉工艺、offer packaging、证据、enterprise-readiness、thought leadership、定价、客户 strategic tension)为每个竞品评分,使用明确 1–5 rubrics 和 tension-plot。位于 competitive-report-structure 之前。
基于 SOC 职业分类
正在显示 SKILL.md
| name | vite-patterns |
| description | Vite 构建工具模式,包括配置、插件、HMR、环境变量、代理设置、SSR、库模式、依赖预打包和构建优化。在处理 vite.config.ts、Vite 插件或基于 Vite 的项目时激活。 |
| origin | ECC |
适用于 Vite 8+ 项目的构建工具和开发服务器模式。涵盖配置、环境变量、代理设置、库模式、依赖预打包和常见生产环境陷阱。
vite.config.ts 或 vite.config.js.env 文件build.lib 发布库node_modules/.vite 下,后续启动跳过此工作。VITE_ 前缀的变量成为包中的公共常量;所有未加前缀的变量对客户端代码不可见。// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
resolve: {
alias: { '@': new URL('./src', import.meta.url).pathname },
},
})
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd()) // 仅 VITE_ 前缀(安全)
return {
plugins: [react()],
server: command === 'serve' ? { port: 3000 } : undefined,
define: {
__API_URL__: JSON.stringify(env.VITE_API_URL),
},
}
})
| 键 | 默认值 | 描述 |
|---|---|---|
root | '.' | 项目根目录(index.html 所在位置) |
base | '/' | 部署资产的公共基础路径 |
envPrefix | 'VITE_' | 客户端暴露的环境变量前缀 |
build.outDir | 'dist' | 输出目录 |
build.minify | 'oxc' | 压缩器('oxc'、'terser' 或 false) |
build.sourcemap | false | true、'inline' 或 'hidden' |
大多数插件需求都可以通过少数维护良好的包来满足。在编写自己的插件之前先尝试这些。
| 插件 | 用途 | 何时使用 |
|---|---|---|
@vitejs/plugin-react-swc | 通过 SWC 的 React HMR + Fast Refresh | React 应用的默认选择(比 Babel 变体更快) |
@vitejs/plugin-react | 通过 Babel 的 React HMR + Fast Refresh | 仅在你需要 Babel 插件时使用(emotion、MobX 装饰器) |
@vitejs/plugin-vue | Vue 3 SFC 支持 | Vue 应用 |
vite-plugin-checker | 在工作线程中运行 tsc + ESLint,带 HMR 覆盖 | 任何 TypeScript 应用 — Vite 在 vite build 时不进行类型检查 |
vite-tsconfig-paths | 遵循 tsconfig.json 的 paths 别名 | 任何时候 tsconfig.json 中已有别名 |
vite-plugin-dts | 在库模式中生成 .d.ts 文件 | 发布 TypeScript 库 |
vite-plugin-svgr | 将 SVG 作为 React 组件导入 | 使用 SVG 作为组件的 React 应用 |
rollup-plugin-visualizer | 包树形图/旭日图报告 | 定期包大小审计(使用 enforce: 'post') |
vite-plugin-pwa | 零配置 PWA + Workbox | 离线可用应用 |
关键提醒: vite build 只转译而不进行类型检查。类型错误会静默发布到生产环境,除非你添加 vite-plugin-checker 或在 CI 中运行 tsc --noEmit。
编写是罕见的 — 大多数需求已被现有插件覆盖。确实需要时,先在 vite.config.ts 中内联编写,仅在需要复用时才提取。
// vite.config.ts — 最小内联插件
function myPlugin(): Plugin {
return {
name: 'my-plugin', // 必需,必须唯一
enforce: 'pre', // 'pre' | 'post'(可选)
apply: 'build', // 'build' | 'serve'(可选)
transform(code, id) {
if (!id.endsWith('.custom')) return
return { code: transformCustom(code), map: null }
},
}
}
关键钩子: transform(修改源码)、resolveId + load(虚拟模块)、transformIndexHtml(注入 HTML)、configureServer(添加开发中间件)、hotUpdate(自定义 HMR — 在 v7+ 中替代已弃用的 handleHotUpdate)。
虚拟模块使用 \0 前缀约定 — resolveId 返回 '\0virtual:my-id' 使其他插件跳过它。用户代码导入 'virtual:my-id'。
完整的插件 API,参见 vite.dev/guide/api-plugin。开发时使用 vite-plugin-inspect 调试转换管道。
框架插件(@vitejs/plugin-react、@vitejs/plugin-vue 等)自动处理 HMR。仅在构建需要在更新间持久化状态的自定义状态存储、开发工具或框架无关工具时,才直接使用 import.meta.hot。
// src/store.ts — 原生模块的手动 HMR
if (import.meta.hot) {
// 在更新间持久化状态(必须修改,绝不要重新赋值 .data)
import.meta.hot.data.count = import.meta.hot.data.count ?? 0
// 在模块替换前清理副作用
import.meta.hot.dispose((data) => clearInterval(data.intervalId))
// 接受此模块自身的更新
import.meta.hot.accept()
}
所有 import.meta.hot 代码在生产构建中会被 tree-shaking 移除 — 无需手动移除守卫。
Vite 按 .env、.env.local、.env.[mode]、.env.[mode].local 的顺序加载(后者覆盖前者);*.local 文件被 gitignore,用于本地密钥。
只有带 VITE_ 前缀的变量会暴露给客户端代码:
import.meta.env.VITE_API_URL // string
import.meta.env.MODE // 'development' | 'production' | 自定义
import.meta.env.BASE_URL // base 配置值
import.meta.env.DEV // boolean
import.meta.env.PROD // boolean
import.meta.env.SSR // boolean
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd()) // 仅 VITE_ 前缀(安全)
return {
define: {
__API_URL__: JSON.stringify(env.VITE_API_URL),
},
}
})
VITE_ 前缀不是安全边界任何带 VITE_ 前缀的变量都会在构建时静态内联到客户端包中。压缩、base64 编码和禁用 source map 都不能隐藏它。有决心的攻击者可以从发布的 JavaScript 中提取任何 VITE_ 变量。
规则: 只有公共值(API URL、功能标志、公钥)才放在 VITE_ 变量中。密钥(API 令牌、数据库 URL、私钥)必须存在于服务端 API 或无服务器函数之后。
loadEnv('') 陷阱// 错误:传递 '' 作为第三个参数会加载所有环境变量 — 包括服务端密钥 —
// 并使它们可通过 `define` 内联到客户端代码中。
const env = loadEnv(mode, process.cwd(), '')
// 正确:显式前缀列表
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])
生产环境的 source map 会泄露你的原始源代码。除非你上传到错误跟踪器(Sentry、Bugsnag)并在之后删除本地副本,否则禁用它们:
build: {
sourcemap: false, // 默认 — 保持这样
}
.gitignore 检查清单.env.local、.env.*.local — 本地密钥覆盖dist/ — 构建输出node_modules/.vite — 预打包缓存(过期条目导致幽灵错误)// vite.config.ts — server.proxy
server: {
proxy: {
'/foo': 'http://localhost:4567', // 字符串简写
'/api': {
target: 'http://localhost:8080',
changeOrigin: true, // 虚拟主机后端需要
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
}
对于 WebSocket 代理,在路由配置中添加 ws: true。
// vite.config.ts — build.rolldownOptions
build: {
rolldownOptions: {
output: {
// 对象形式:分组特定包
manualChunks: {
'react-vendor': ['react', 'react-dom'],
'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
},
},
},
}
// 函数形式:按启发式分割
manualChunks(id) {
if (id.includes('node_modules/react')) return 'react-vendor'
if (id.includes('node_modules')) return 'vendor'
}
桶文件(从目录中重新导出所有内容的 index.ts)会强制 Vite 加载每个重新导出的文件,即使你只导入一个符号。这是官方文档标记的头号开发服务器减速问题。
// 错误 — 导入一个工具函数会强制 Vite 加载整个桶
import { slash } from '@/utils'
// 正确 — 直接导入,只加载一个文件
import { slash } from '@/utils/slash'
每个隐式扩展名会强制最多 6 次文件系统检查(通过 resolve.extensions)。在大型代码库中,这会累积。
// 错误
import Component from './Component'
// 正确
import Component from './Component.tsx'
缩小 tsconfig.json 的 allowImportingTsExtensions + resolve.extensions,仅包含你实际使用的扩展名。
server.warmup.clientFiles 在浏览器请求之前预转换已知的热入口 — 消除大型应用上的冷加载请求瀑布。
// vite.config.ts
server: {
warmup: {
clientFiles: ['./src/main.tsx', './src/routes/**/*.tsx'],
},
}
当 vite dev 感觉慢时,以 vite --profile 启动,与应用交互,然后按 p+enter 保存 .cpuprofile。加载到 Speedscope 中查找哪些插件在消耗时间 — 通常是社区插件的 buildStart、config 或 configResolved 钩子。
发布 npm 包时,使用 build.lib。两个比配置细节更重要的问题:
vite-plugin-dts 或单独运行 tsc --emitDeclarationOnly。// vite.config.ts
build: {
lib: {
entry: 'src/index.ts',
formats: ['es', 'cjs'],
fileName: (format) => `my-lib.${format}.js`,
},
rolldownOptions: {
external: ['react', 'react-dom', 'react/jsx-runtime'], // 每个对等依赖
},
}
裸 createServer({ middlewareMode: true }) 设置是框架作者领域。大多数应用应使用 Nuxt、Remix、SvelteKit、Astro 或 TanStack Start。作为框架用户,你会在依赖项在 SSR 中出错时调整外部化配置:
// vite.config.ts — ssr 选项
ssr: {
external: ['node-native-package'], // 在 SSR 包中保持为 require()
noExternal: ['esm-only-package'], // 强制打包到 SSR 输出(修复大多数 SSR 错误)
target: 'node', // 'node' 或 'webworker'
}
Vite 预打包依赖项以将 CJS/UMD 转换为 ESM 并减少请求数。
// vite.config.ts — optimizeDeps
optimizeDeps: {
include: [
'lodash-es', // 强制预打包已知重型依赖
'cjs-package', // 导致互操作问题的 CJS 依赖
'deep-lib/components/**', // 深度导入的 glob 模式
],
exclude: ['local-esm-package'], // 排除的必须是有效 ESM
force: true, // 忽略缓存,重新优化(临时调试)
}
开发使用 esbuild/Rolldown 进行转换;构建使用 Rolldown 进行打包。CJS 库在两者之间可能有不同表现。部署前始终用 vite build && vite preview 验证。
新构建产生新的分块哈希。有活跃会话的用户请求不再存在的旧文件名。Vite 没有内置解决方案。缓解措施:
dist/assets/ 文件在一个部署窗口内可用Vite 默认绑定到 localhost,从容器外部无法访问:
// vite.config.ts — Docker/容器设置
server: {
host: true, // 绑定 0.0.0.0
hmr: { clientPort: 3000 }, // 如果在反向代理后面
}
Vite 限制文件服务到项目根目录。根目录之外的包被阻止:
// vite.config.ts — monorepo 文件访问
server: {
fs: {
allow: ['..'], // 允许父目录(工作区根)
},
}
// 错误:将 envPrefix 设为 '' 会向客户端暴露所有环境变量(包括密钥)
envPrefix: ''
// 错误:假设 require() 在应用源代码中可用 — Vite 是 ESM 优先的
const lib = require('some-lib') // 改用 import
// 错误:将每个 node_module 拆分成单独的块 — 创建数百个小文件
manualChunks(id) {
if (id.includes('node_modules')) {
return id.split('node_modules/')[1].split('/')[0] // 每个包一个块
}
}
// 错误:在库模式中未外部化对等依赖 — 导致重复运行时错误
// build.lib 没有 rolldownOptions.external
// 错误:使用已弃用的 esbuild 压缩器
build: { minify: 'esbuild' } // 使用 'oxc'(默认)或 'terser'
// 错误:通过重新赋值修改 import.meta.hot.data
import.meta.hot.data = { count: 0 } // 错误:必须修改属性,不能重新赋值
import.meta.hot.data.count = 0 // 正确
流程反模式:
vite preview 不是生产服务器 — 它是构建包的冒烟测试。将 dist/ 部署到真正的静态主机(NGINX、Cloudflare Pages、Vercel static)或使用多阶段 Dockerfile。vite build 进行类型检查 — 它只转译。类型错误会静默发布到生产环境。添加 vite-plugin-checker 或在 CI 中运行 tsc --noEmit。@vitejs/plugin-legacy — 它会使包膨胀约 40%,破坏 source map 包分析器,对 95%+ 使用现代浏览器的用户来说是不必要的。基于真实分析数据而非假设来启用它。tsconfig.json paths 重复的 resolve.alias 条目 — 改用 vite-tsconfig-paths。在 Excalidraw 和 PostHog 中观察到此问题;新项目中避免使用。node_modules/.vite — 预打包缓存导致幽灵错误。切换分支或修补依赖后清除它。| 模式 | 何时使用 |
|---|---|
defineConfig | 始终使用 — 提供类型推断 |
loadEnv(mode, root, ['VITE_']) | 在配置中访问环境变量(显式前缀) |
vite-plugin-checker | 任何 TypeScript 应用(填补类型检查空白) |
vite-tsconfig-paths | 替代手动编写的 resolve.alias |
optimizeDeps.include | 导致互操作问题的 CJS 依赖 |
server.proxy | 在开发中将 API 请求路由到后端 |
server.host: true | Docker、容器、远程访问 |
server.warmup.clientFiles | 预转换热路径路由 |
build.lib + external | 发布 npm 包 |
manualChunks(对象) | 厂商包分割 |
vite --profile | 调试慢开发服务器 |
vite build && vite preview | 本地冒烟测试生产包(不是生产服务器) |
frontend-patterns — React 组件模式docker-patterns — 使用 Vite 的容器化开发nextjs-turbopack — Next.js 的替代打包器