前端工程化实战:从包管理到 Vite 配置,一套下来全明白
你还在
npm install之后一脸懵?.env文件不知道放哪?代理配置总是跨域?每次打包都像玄学?
本文手把手带你梳理前端工程化的核心链路:包管理器、Vite 开发服务器、环境变量与代理,让你真正掌控项目配置。
目录
- [包管理:npm、yarn、pnpm 怎么选?](#包管理:npm、yarn、pnpm 怎么选? "#1-%E5%8C%85%E7%AE%A1%E7%90%86npm-yarn-pnpm-%E6%80%8E%E4%B9%88%E9%80%89")
- Vite:下一代前端工具链
- 环境变量:开发/生产/测试的配置分离
- 代理配置:告别跨域烦恼
- [完整实战:一个 Vue 3 + Vite 项目的工程化配置](#完整实战:一个 Vue 3 + Vite 项目的工程化配置 "#5-%E5%AE%8C%E6%95%B4%E5%AE%9E%E6%88%98%E4%B8%80%E4%B8%AA-vue-3--vite-%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%B7%A5%E7%A8%8B%E5%8C%96%E9%85%8D%E7%BD%AE")
- 常见问题与排查技巧
- 总结与进阶方向
1. 包管理:npm、yarn、pnpm 怎么选?
包管理器是工程化的第一步。它的职责是:安装依赖、管理版本、锁定依赖树。
1.1 npm(Node.js 内置)
bash
npm init -y # 初始化
npm install vue # 安装依赖,写入 dependencies
npm install -D vite # 开发依赖,写入 devDependencies
- 优点:自带,不用额外安装。
- 缺点 :早期版本慢、
node_modules嵌套深(已改进)。锁文件package-lock.json。
1.2 yarn(Facebook)
bash
yarn init -y
yarn add vue
yarn add -D vite
- 优点 :速度快(并行下载),缓存机制好。锁文件
yarn.lock。 - 缺点 :需要单独安装,早期版本也是扁平化不够好(1.x 有
nohoist,2+ 改用 PnP 但兼容性问题)。
1.3 pnpm(性能之王)
bash
pnpm init
pnpm add vue
pnpm add -D vite
- 优点:使用硬链接和符号链接,节省磁盘空间,安装极快。严格避免幽灵依赖(未声明的依赖不能引用)。
- 缺点:兼容性略差(某些工具对 pnpm 支持不完善,但近年已基本解决)。
选型建议:
- 个人项目或团队无特殊要求:pnpm(快、省空间、规范)。
- 团队已有 npm 锁文件:继续用 npm。
- 需要兼容老项目:yarn 1.x。
2. Vite:下一代前端工具链
Vite 利用浏览器原生 ES Module 实现开发时按需编译,生产环境使用 Rollup 打包。
2.1 创建项目
bash
pnpm create vite my-app --template vue-ts
cd my-app
pnpm install
pnpm run dev
2.2 vite.config.ts 核心配置
ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
server: {
port: 5173,
open: true, // 自动打开浏览器
proxy: { // 代理配置(后面细讲)
'/api': 'http://localhost:8080'
}
},
build: {
outDir: 'dist',
sourcemap: false,
rollupOptions: {
// 手动分包等
}
},
css: {
preprocessorOptions: {
scss: { additionalData: `@import "@/styles/variables.scss";` }
}
}
})
2.3 为什么 Vite 快?
- 开发时:预构建依赖(esbuild),源码按需编译(只编译请求的模块)。
- 热更新(HMR):基于 ESM 的精确模块替换,无需打包。
- 生产环境:使用 Rollup 打包(成熟、生态好)。
3. 环境变量:开发/生产/测试的配置分离
3.1 文件命名约定
Vite 支持以下 .env 文件(放在项目根目录):
bash
.env # 所有环境都会加载
.env.development # 开发环境(npm run dev)
.env.production # 生产环境(npm run build)
.env.test # 测试环境(可选)
优先级 :具体环境的文件 > .env。
3.2 定义变量
变量名必须以 VITE_ 开头才会暴露给客户端:
ini
# .env.development
VITE_API_BASE_URL = http://localhost:3000
VITE_APP_TITLE = 开发环境
# 非 VITE_ 前缀不会被客户端访问
DB_PASSWORD = 123456
3.3 在代码中使用
js
console.log(import.meta.env.VITE_API_BASE_URL)
console.log(import.meta.env.MODE) // 'development'
3.4 TypeScript 类型提示
在 src/vite-env.d.ts 中:
ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string
readonly VITE_APP_TITLE: string
}
4. 代理配置:告别跨域烦恼
前端开发时,前端服务(http://localhost:5173)请求后端 API(如 http://localhost:8080/api/user)会触发跨域。Vite 代理可以转发请求,避免 CORS。
4.1 基本代理
ts
server: {
proxy: {
'/api': 'http://localhost:8080'
}
}
效果:/api/user → http://localhost:8080/api/user
4.2 重写路径
如果后端接口不带 /api 前缀:
ts
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
/api/user → http://localhost:8080/user
4.3 多个代理
ts
proxy: {
'/api': 'http://localhost:8080',
'/uploads': 'http://localhost:8081',
'/socket.io': {
target: 'ws://localhost:3000',
ws: true // 启用 WebSocket 代理
}
}
4.4 为什么需要 changeOrigin: true?
有些后端会验证请求的 Host 头。设置为 true 时,代理会把 Host 改为目标服务器的地址,避免被拒。
5. 完整实战:一个 Vue 3 + Vite 项目的工程化配置
5.1 项目结构
css
my-project/
├── .env.development
├── .env.production
├── .gitignore
├── index.html
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
├── vite.config.ts
└── src/
├── main.ts
├── App.vue
├── api/
│ └── request.ts
└── vite-env.d.ts
5.2 .env.development
ini
VITE_API_BASE_URL=/api
VITE_APP_TITLE=开发环境
5.3 vite.config.ts
ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
server: {
port: 5173,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
build: {
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia']
}
}
}
}
})
5.4 src/api/request.ts
ts
const baseURL = import.meta.env.VITE_API_BASE_URL
export const fetchUser = () => {
return fetch(`${baseURL}/user`)
}
5.5 运行与构建
bash
pnpm dev # 开发模式,使用 .env.development
pnpm build # 构建生产包,使用 .env.production
pnpm preview # 预览生产包
6. 常见问题与排查技巧
6.1 环境变量不生效?
- 确认变量以
VITE_开头。 - 修改
.env文件后需要重启dev服务。 - 检查是否在正确的根目录。
6.2 代理不工作?
- 确认后端服务已启动。
- 检查路径重写规则是否正确。
- 浏览器 Network 面板查看请求是否被代理(请求 URL 应仍是
/api/xxx,但响应来自后端)。 - 开启
changeOrigin: true。
6.3 模块别名 @ 报错?
- 确保
vite.config.ts中配置了resolve.alias。 - TypeScript 项目需要在
tsconfig.json中同步配置:
json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
6.4 打包后图片/字体路径错误?
设置 base 选项:
ts
export default defineConfig({
base: '/my-app/' // 部署到子路径时
})
6.5 幽灵依赖(直接使用未在 package.json 声明的包)
pnpm 默认禁止幽灵依赖,可以放宽:
yaml
# .npmrc
shamefully-hoist=true
但推荐显式安装需要的依赖。
7. 总结与进阶方向
7.1 本文核心回顾
- 包管理:pnpm 性能最佳,npm 最通用。
- Vite:开发用 ESM 按需编译,生产用 Rollup 打包。
- 环境变量 :
.env文件 +import.meta.env,VITE_前缀暴露给客户端。 - 代理:解决开发跨域,支持路径重写和 WebSocket。
7.2 进阶方向
- Monorepo:pnpm workspace、turborepo。
- CI/CD:GitHub Actions、GitLab CI 自动化构建部署。
- 代码规范:ESLint + Prettier + Husky + lint-staged。
- 测试:Vitest(单元测试)、Playwright(E2E)。
- 性能分析 :
vite-bundle-visualizer、rollup-plugin-visualizer。