5 分钟用 Vite 起一个 React + TypeScript 项目(可上生产的最小配置)

CRA 已经废弃,Next.js 太重——纯 SPA 现在的标准答案是 Vite。
下面建立一个开箱即用的最小项目,包含路由、CSS 模块化、ESLint、
开发 + 生产构建。

1. 脚手架

npm create vite@latest my-app -- --template react-ts
cd my-app
npm install

--template react-ts 直接给 TypeScript。

2. 装常用依赖

npm i react-router-dom
npm i -D @types/node prettier eslint-config-prettier

3. 给 tsconfig.json 加 path alias

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

让 Vite 也认 alias:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'node:path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  server: { port: 5173, host: true },
  build: {
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: {
          react: ['react', 'react-dom', 'react-router-dom'],
        },
      },
    },
  },
})

manualChunks 把 React 切成独立 chunk,业务代码变化不会重新拉这部分。

4. 主入口

// src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from '@/App'
import '@/index.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>,
)

5. App + 路由

// src/App.tsx
import { Routes, Route, Link } from 'react-router-dom'
import Home from '@/pages/Home'
import About from '@/pages/About'

export default function App() {
  return (
    <>
      <nav>
        <Link to="/">Home</Link> | <Link to="/about">About</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </>
  )
}
// src/pages/Home.tsx
export default function Home() {
  return <h1>Hello</h1>
}

6. CSS Modules

/* src/pages/Home.module.css */
.title { font-size: 2rem; color: #2563eb; }
import s from './Home.module.css'
export default function Home() {
  return <h1 className={s.title}>Hello</h1>
}

TypeScript 默认认得 .module.css —— vite/client 类型定义里包含了。

7. ESLint + Prettier

npm i -D eslint @eslint/js typescript-eslint eslint-plugin-react-hooks \
        eslint-plugin-react-refresh prettier

eslint.config.js

import js from '@eslint/js'
import ts from 'typescript-eslint'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default ts.config(
  { ignores: ['dist'] },
  js.configs.recommended,
  ...ts.configs.recommended,
  {
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': 'warn',
    },
  },
)

package.json 加 script:

{
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "preview": "vite preview",
    "lint": "eslint .",
    "format": "prettier -w ."
  }
}

8. 跑

npm run dev          # 开发,HMR
# http://localhost:5173

npm run build        # tsc 类型检查 + Vite 打包,输出到 dist/
npm run preview      # 本地预览生产构建

9. 部署(静态托管)

npm run build
# dist/ 直接 rsync 到任何静态服务器:
rsync -avz --delete ./dist/ user@server:/var/www/myapp/

服务端 nginx:

server {
    listen 80;
    server_name myapp.example.com;
    root /var/www/myapp;
    index index.html;

    # SPA 路由:所有未命中文件的请求都 fallback 到 index.html
    location / { try_files $uri $uri/ /index.html; }

    # 资源缓存 1 年(文件名带 hash 所以安全)
    location ~* \.(css|js|png|jpg|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

踩过的坑

  • 用 alias @/ 后 IDE 不识别 → 重启 TypeScript Server(VSCode:Cmd+Shift+P
    → "TypeScript: Restart TS Server")。
  • HMR 突然不工作:检查文件名首字母是否大写。Home.tsx 默认 export
    必须是 Home(首字母大写),否则 react-refresh 不接管。
  • 生产构建 hash 文件名后部署时新文件先到,旧 index.html 还在引用,
    瞬间 404。解决:先部署 assets/ 再部署 index.html,并保留旧 hash
    文件 2-3 个版本。
  • vite preview 不能完全替代真实生产 nginx,特别是 try_files fallback ——
    preview 自带 SPA fallback,nginx 没配就 404。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。