第17期 | 工程化:Vite构建与项目规范——让项目结构像专业团队一样
第17期 | 工程化:Vite构建与项目规范——让项目结构像专业团队一样
🎯 今天你将学会
- 理解 Vite 为什么比 Webpack 快
- 配置路径别名、环境变量、代理、插件
- 建立合理的项目目录结构
- 配置 ESLint + Prettier + Husky 代码规范三件套
- 用 AI 辅助配置 Vite 插件
📖 核心知识
1. 为什么用 Vite:构建工具的演进
Webpack 时代的问题(2015-2020):
- 启动慢:需要把所有模块打包成 bundle 才能启动开发服务器,项目越大越慢
- 热更新慢:改一行代码,需要重新打包整个 bundle
Vite 的解法(2020至今):
- 开发时不打包:直接利用浏览器的 ES Module,按需加载文件
- 热更新极快:只更新改动的那个模块,毫秒级响应
- 生产构建用 Rollup:输出高度优化的 bundle
传统 Webpack:
源码 → 全部打包成 bundle.js → 开发服务器 → 浏览器
Vite 开发模式:
浏览器请求 → Vite 服务器实时转换对应模块 → 返回给浏览器
实测对比(中型项目):
| 操作 | Webpack | Vite |
|---|---|---|
| 冷启动 | 30-60s | 1-3s |
| 热更新 | 3-5s | <100ms |
| 生产构建 | 60s | 30s |
2. 创建 Vite 项目
# 创建 React + TypeScript 项目
npm create vite@latest my-project -- --template react-ts
cd my-project
npm install
npm run dev
项目初始结构:
my-project/
├── public/ # 静态资源(不会被处理,原样输出)
│ └── favicon.ico
├── src/
│ ├── assets/ # 会被 Vite 处理的资源(图片等)
│ ├── App.tsx
│ ├── App.css
│ ├── main.tsx # 入口文件
│ └── vite-env.d.ts # 环境变量类型声明
├── index.html # 根 HTML(Vite 的真正入口)
├── vite.config.ts # Vite 配置文件
├── tsconfig.json
└── package.json
3. vite.config.ts 配置详解
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
// 插件
plugins: [
react(), // React 支持(JSX 转换 + 热更新)
],
// 路径别名:让 @/components 代替 ../../components
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@hooks': path.resolve(__dirname, './src/hooks'),
'@stores': path.resolve(__dirname, './src/stores'),
'@utils': path.resolve(__dirname, './src/utils'),
'@types': path.resolve(__dirname, './src/types'),
},
},
// 开发服务器
server: {
port: 3000, // 开发端口
open: true, // 启动时自动打开浏览器
// API 代理:解决开发时的跨域问题
proxy: {
'/api': {
target: 'http://localhost:8080', // 后端地址
changeOrigin: true,
// 可选:重写路径(把 /api 前缀去掉)
// rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
// 构建配置
build: {
outDir: 'dist', // 输出目录
sourcemap: false, // 生产不需要 sourcemap
minify: 'terser', // 压缩方式
// 分包策略:把大型依赖单独打包,提升缓存命中率
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
ui: ['antd'],
},
},
},
},
// CSS 配置
css: {
preprocessorOptions: {
scss: {
// 全局注入 SCSS 变量(不需要在每个文件 import)
additionalData: `@import "@/styles/variables.scss";`,
},
},
modules: {
// CSS Modules 类名转换规则
localsConvention: 'camelCase',
},
},
});
同步更新 tsconfig.json 的路径别名:
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"]
}
}
}
4. 环境变量管理
Vite 通过 .env 文件管理环境变量:
# .env(所有环境都读取)
VITE_APP_NAME=My App
# .env.development(开发环境)
VITE_API_URL=http://localhost:8080
VITE_DEBUG=true
# .env.production(生产环境)
VITE_API_URL=https://api.myapp.com
VITE_DEBUG=false
# .env.local(本地覆盖,不提交 git)
VITE_API_KEY=my_secret_key
注意:只有 VITE_ 前缀的变量才会暴露给前端代码!
// 在代码中使用
const apiUrl = import.meta.env.VITE_API_URL;
const isDebug = import.meta.env.VITE_DEBUG === 'true';
// 添加类型声明(避免 TS 报 any 类型)
// src/vite-env.d.ts
interface ImportMetaEnv {
readonly VITE_API_URL: string;
readonly VITE_APP_NAME: string;
readonly VITE_DEBUG: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
5. 专业的项目目录结构
src/
├── assets/ # 图片、字体、SVG 等静态资源
│ ├── images/
│ └── fonts/
│
├── components/ # 公共组件
│ ├── ui/ # 基础 UI 组件(Button、Input、Modal 等)
│ │ ├── Button/
│ │ │ ├── Button.tsx
│ │ │ ├── Button.module.css
│ │ │ └── index.ts # 统一导出
│ │ └── Input/
│ └── layout/ # 布局组件(Header、Sidebar、Footer)
│
├── features/ # 按业务功能划分(Feature-based 架构)
│ ├── auth/ # 认证功能
│ │ ├── components/ # 该功能专属组件
│ │ ├── hooks/ # 该功能专属 hooks
│ │ ├── stores/ # 该功能的状态
│ │ ├── api.ts # 该功能的 API 调用
│ │ └── types.ts # 该功能的类型定义
│ ├── posts/
│ └── dashboard/
│
├── hooks/ # 全局通用自定义 Hooks
│ ├── useFetch.ts
│ ├── useDebounce.ts
│ └── useLocalStorage.ts
│
├── lib/ # 第三方库的封装/初始化
│ ├── axios.ts # axios 实例配置
│ └── dayjs.ts # dayjs 配置(时区、插件)
│
├── pages/ # 路由页面
│ ├── Home/
│ ├── PostDetail/
│ └── Profile/
│
├── router/ # 路由配置
│ └── index.tsx
│
├── stores/ # 全局状态(Zustand)
│ ├── userStore.ts
│ └── notificationStore.ts
│
├── styles/ # 全局样式
│ ├── global.css
│ └── variables.scss
│
├── types/ # 全局类型定义
│ ├── api.ts # API 响应类型
│ └── models.ts # 业务模型类型
│
├── utils/ # 工具函数
│ ├── format.ts
│ └── validate.ts
│
├── App.tsx
└── main.tsx
6. ESLint + Prettier + Husky:代码规范三件套
安装:
npm install -D eslint prettier eslint-config-prettier eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser lint-staged husky
.eslintrc.cjs 配置:
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
'prettier', // 必须放最后,覆盖与 Prettier 冲突的规则
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-console': ['warn', { allow: ['warn', 'error'] }], // 允许 console.warn/error
},
};
.prettierrc 配置:
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"arrowParens": "avoid"
}
配置 Husky(提交前自动 lint):
# 初始化 husky
npx husky init
# .husky/pre-commit 内容:
npx lint-staged
package.json 中配置 lint-staged:
{
"lint-staged": {
"src/**/*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"src/**/*.{css,scss,json,md}": [
"prettier --write"
]
}
}
现在每次 git commit 前,会自动对暂存区的文件运行 lint 和格式化,确保提交的代码永远规范。
🤖 AI协作实战:AI 解释 Vite 插件配置
场景: 我想给项目加上 SVG 图标组件化支持,但不知道怎么配置。
我给 AI 的 Prompt:
我的 Vite + React + TypeScript 项目需要支持将 SVG 文件作为 React 组件导入(而不是作为图片URL)。
比如:import { ReactComponent as Logo } from './logo.svg'
或者:import Logo from './logo.svg?react'
请帮我:
1. 安装什么包
2. 如何配置 vite.config.ts
3. 给出使用示例
4. 说明这两种导入方式的区别
AI 的回答(整理):
安装:npm install -D vite-plugin-svgr
配置:
import svgr from 'vite-plugin-svgr';
export default defineConfig({
plugins: [
react(),
svgr(), // 添加这行
],
});
两种使用方式:
// 方式1:?react 查询参数(推荐,更明确)
import Logo from './logo.svg?react';
<Logo className="logo" width={32} height={32} />
// 方式2:命名导入(兼容 CRA 风格,需配置 exportAsDefault: false)
import { ReactComponent as Logo } from './logo.svg';
<Logo className="logo" />
TypeScript 类型声明(加到 vite-env.d.ts):
declare module '*.svg?react' {
import React from 'react';
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
💻 动手练习
简单: 创建一个新的 Vite + React + TS 项目,配置路径别名 @ 指向 src,然后在组件中用 @/utils/format.ts 导入一个格式化函数验证配置生效。
中等: 在项目中配置三个环境:
- 开发环境(
.env.development):API 地址指向 localhost:3000 - 测试环境(
.env.staging):API 地址指向 staging.myapp.com - 生产环境(
.env.production):API 地址指向 api.myapp.com - 在首页显示当前环境名称和 API 地址
挑战: 完整配置代码规范三件套(ESLint + Prettier + Husky),然后:
- 故意写一个违反 ESLint 规则的代码(比如未使用的变量)
- 尝试 git commit,观察是否被阻止
- 修复后再次 commit,确认流程正常
📌 本期要点
- Vite 快的原因:开发时不打包,利用浏览器原生 ES Module + 按需编译
- 路径别名:在
vite.config.ts和tsconfig.json都要配,缺一不可 - 环境变量必须加
VITE_前缀,否则前端访问不到 - Feature-based 目录结构比按类型分目录更适合大型项目,修改某功能时只改一个文件夹
- Husky + lint-staged:让"提交即规范",团队协作的基础设施
🔗 下期预告
第18期:实战2——Todo App 升级版,把 CRUD + Router + Zustand + TypeScript 全部整合在一个真实项目里,AI 结对编程,你主导决策。
如果你没有苹果电脑,需要上传ios到APPStore可以访问以下网站
iPA上传工具 - IPA解析与AppStore提交
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)