前端工程化实战:从包管理到 Vite 配置,一套下来全明白

0 阅读5分钟

前端工程化实战:从包管理到 Vite 配置,一套下来全明白

你还在 npm install 之后一脸懵?.env 文件不知道放哪?
代理配置总是跨域?每次打包都像玄学?
本文手把手带你梳理前端工程化的核心链路:包管理器、Vite 开发服务器、环境变量与代理,让你真正掌控项目配置。


目录

  1. 包管理:npm、yarn、pnpm 怎么选?
  2. Vite:下一代前端工具链
  3. 环境变量:开发/生产/测试的配置分离
  4. 代理配置:告别跨域烦恼
  5. 完整实战:一个 Vue 3 + Vite 项目的工程化配置
  6. 常见问题与排查技巧
  7. 总结与进阶方向

1. 包管理:npm、yarn、pnpm 怎么选?

包管理器是工程化的第一步。它的职责是:安装依赖、管理版本、锁定依赖树。

1.1 npm(Node.js 内置)

npm init -y          # 初始化
npm install vue      # 安装依赖,写入 dependencies
npm install -D vite  # 开发依赖,写入 devDependencies
  • 优点:自带,不用额外安装。
  • 缺点:早期版本慢、node_modules 嵌套深(已改进)。锁文件 package-lock.json

1.2 yarn(Facebook)

yarn init -y
yarn add vue
yarn add -D vite
  • 优点:速度快(并行下载),缓存机制好。锁文件 yarn.lock
  • 缺点:需要单独安装,早期版本也是扁平化不够好(1.x 有 nohoist,2+ 改用 PnP 但兼容性问题)。

1.3 pnpm(性能之王)

pnpm init
pnpm add vue
pnpm add -D vite
  • 优点:使用硬链接和符号链接,节省磁盘空间,安装极快。严格避免幽灵依赖(未声明的依赖不能引用)。
  • 缺点:兼容性略差(某些工具对 pnpm 支持不完善,但近年已基本解决)。

选型建议

  • 个人项目或团队无特殊要求:pnpm(快、省空间、规范)。
  • 团队已有 npm 锁文件:继续用 npm。
  • 需要兼容老项目:yarn 1.x。

2. Vite:下一代前端工具链

Vite 利用浏览器原生 ES Module 实现开发时按需编译,生产环境使用 Rollup 打包。

2.1 创建项目

pnpm create vite my-app --template vue-ts
cd my-app
pnpm install
pnpm run dev

2.2 vite.config.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 文件(放在项目根目录):

.env                # 所有环境都会加载
.env.development    # 开发环境(npm run dev)
.env.production     # 生产环境(npm run build)
.env.test           # 测试环境(可选)

优先级:具体环境的文件 > .env

3.2 定义变量

变量名必须以 VITE_ 开头才会暴露给客户端:

# .env.development
VITE_API_BASE_URL = http://localhost:3000
VITE_APP_TITLE = 开发环境
# 非 VITE_ 前缀不会被客户端访问
DB_PASSWORD = 123456

3.3 在代码中使用

console.log(import.meta.env.VITE_API_BASE_URL)
console.log(import.meta.env.MODE)  // 'development'

3.4 TypeScript 类型提示

src/vite-env.d.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 基本代理

server: {
  proxy: {
    '/api': 'http://localhost:8080'
  }
}

效果:/api/userhttp://localhost:8080/api/user

4.2 重写路径

如果后端接口不带 /api 前缀:

server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, '')
    }
  }
}

/api/userhttp://localhost:8080/user

4.3 多个代理

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 项目结构

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

VITE_API_BASE_URL=/api
VITE_APP_TITLE=开发环境

5.3 vite.config.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

const baseURL = import.meta.env.VITE_API_BASE_URL

export const fetchUser = () => {
  return fetch(`${baseURL}/user`)
}

5.5 运行与构建

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 中同步配置:
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

6.4 打包后图片/字体路径错误?

设置 base 选项:

export default defineConfig({
  base: '/my-app/'   // 部署到子路径时
})

6.5 幽灵依赖(直接使用未在 package.json 声明的包)

pnpm 默认禁止幽灵依赖,可以放宽:

# .npmrc
shamefully-hoist=true

但推荐显式安装需要的依赖。


7. 总结与进阶方向

7.1 本文核心回顾

  • 包管理:pnpm 性能最佳,npm 最通用。
  • Vite:开发用 ESM 按需编译,生产用 Rollup 打包。
  • 环境变量.env 文件 + import.meta.envVITE_ 前缀暴露给客户端。
  • 代理:解决开发跨域,支持路径重写和 WebSocket。

7.2 进阶方向

  • Monorepo:pnpm workspace、turborepo。
  • CI/CD:GitHub Actions、GitLab CI 自动化构建部署。
  • 代码规范:ESLint + Prettier + Husky + lint-staged。
  • 测试:Vitest(单元测试)、Playwright(E2E)。
  • 性能分析vite-bundle-visualizerrollup-plugin-visualizer

7.3 推荐资源