为什么选择 Vite

Vite 基于原生 ESM,开发期按需编译,冷启动与 HMR 速度极快;生产期使用 Rollup 构建,生态完善。对于中大型 React 项目,可显著提升迭代效率与产物质量。

项目初始化与目录约定

1
2
3
npm create vite@latest hello-react -- --template react-ts
cd hello-react && npm i
npm run dev

建议目录:

1
2
3
4
5
6
7
8
src/
assets/ # 静态资源
components/ # 通用组件
pages/ # 路由页面
hooks/ # 自定义 Hook
stores/ # 状态管理
services/ # 接口调用
utils/ # 工具库

常用配置

  • 路径别名
1
2
3
4
5
// vite.config.ts
import path from 'node:path'
export default defineConfig({
resolve: { alias: { '@': path.resolve(__dirname, 'src') } }
})
  • 环境变量与模式
1
2
3
.env.development
.env.production
VITE_API_BASE=https://api.example.com

使用:import.meta.env.VITE_API_BASE

  • 开发代理
1
2
3
4
5
6
7
8
9
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: p => p.replace(/^\/api/, '')
}
}
}

性能优化

  • 代码分割:路由懒加载
1
const User = lazy(() => import('@/pages/user'))
  • 资源优化:图片使用现代格式(webp/avif)、SVG Icon Sprite;静态资源放入 public/ 享受长缓存
  • 依赖预构建:optimizeDeps.include 指定大体积依赖加速预扫描
  • 构建体积分析
1
2
3
npm i -D rollup-plugin-visualizer
# vite.config.ts
plugins: [visualizer({ open: true })]

质量与规范

  • ESLint + Prettier
1
npm i -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier
  • 单元测试(Vitest)
1
2
// vite.config.ts
test: { environment: 'jsdom' }
  • 端到端(Playwright/Cypress)按需接入

SSR/PWA/国际化(可选)

  • SSR:vite-plugin-ssr/@vitejs/plugin-react-ssr,用于 SEO 与首屏性能
  • PWA:vite-plugin-pwa 实现离线缓存、图标生成
  • i18n:react-i18next 动态加载语言包

部署与 CI/CD

  • 正确设置 base(子路径部署)与 assetsInlineLimit
  • Nginx/Ingress 缓存与 gzip/br 压缩
  • CI 缓存 node_modules 与 Vite 缓存目录 .vite
  • Source Map 仅在需要排障的环境开启,避免泄露源代码

常见踩坑

  • base 未设置导致资源404:子路径部署务必配置 base
  • Hydration mismatch:与后端同构时注意与服务端输出一致
  • CORS:尽量通过反向代理解决,避免浏览器侧跨域复杂度
  • 动态导入路径错误:务必使用绝对别名或模板字符串受限

示例:接口封装与错误边界

1
2
3
4
5
6
// services/http.ts
export async function get<T>(url: string): Promise<T> {
const r = await fetch(import.meta.env.VITE_API_BASE + url, { credentials: 'include' })
if (!r.ok) throw new Error(await r.text())
return r.json()
}
1
2
3
4
5
6
// components/ErrorBoundary.tsx
class ErrorBoundary extends React.Component<any, { hasError: boolean }> {
constructor(p:any){ super(p); this.state={hasError:false} }
static getDerivedStateFromError(){ return {hasError:true} }
render(){ return this.state.hasError ? <div>出了点问题</div> : this.props.children }
}

总结

以 Vite 为核心构建链路,配合合理的目录组织、规范化工具、按需优化与自动化部署,可以在保持高迭代效率的同时,获得稳定可维护的工程质量。