【Vite工程化】中后台前端项目实战:从alias/env/proxy到打包配置,一站式搞定统一规范与协作,避开路径、跨域、打包高频坑!

在这里插入图片描述

📑 文章目录

同学们好,我是 Eugene(尤金),一名多年中后台前端开发工程师。

(Eugene 发音 /juːˈdʒiːn/,大家怎么顺口怎么叫就好)

很多前端开发者都会遇到一个瓶颈:

代码能跑,但不够规范;功能能实现,但维护起来特别痛苦;一个人写没问题,一到团队协作就各种混乱、踩坑、返工。

想写出干净、优雅、可维护的专业代码,靠的不是天赋,而是体系化的规范 + 真实实战经验

这一系列《前端规范实战》,我会用大白话 + 真实业务场景,不讲玄学、不堆理论,只分享能直接落地的规范、标准与避坑指南。

帮你从「会写代码」真正升级为「会写优质、可维护、团队级别的代码」。


一、开篇

1.1 适合人群

这是一篇面向「日常写代码」的实战文章,不讲底层原理,重点是:怎么选、为什么这么选、容易踩哪些坑

适合人群:

  • 会写 JS,但对 Vite 配置一知半解的同学
  • 从零开始学 Vite 的小白
  • 想系统梳理配置、规范团队协作的前端

文章会覆盖:路径别名(alias)环境变量(env)开发代理(proxy)打包配置(build)统一项目配置。每个部分都会给出完整示例和说明。

⬆ 返回目录


二、路径别名(alias):告别 ../../../

2.1 为什么要配 alias?

项目结构变深后,经常会出现:

// 没有 alias:从 src/views/user/profile/index.vue 引入工具
import { formatDate } from '../../../../utils/format'

问题在于:路径难读、容易数错层级、移动文件后要大量修改。

配好 alias 后可以改成:

import { formatDate } from '@/utils/format'

含义清晰,也不受目录层级影响。

⬆ 返回目录

2.2 怎么配?

vite.config.js(或 vite.config.ts)中配置:

// vite.config.js
import { defineConfig } from 'vite'
import path from 'path'
import { fileURLToPath } from 'url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@utils': path.resolve(__dirname, './src/utils'),
      '@components': path.resolve(__dirname, './src/components'),
      '@views': path.resolve(__dirname, './src/views'),
      '@assets': path.resolve(__dirname, './src/assets'),
    }
  }
})

说明:

  • @ 映射到 src,最常用
  • @utils@components 等可按业务再细分
  • 建议用 path.resolvefileURLToPath(new URL(...)) 保证路径正确

⬆ 返回目录

2.3 让 IDE 识别 alias(重要)

不配置的话,编辑器和 TypeScript 可能:

  • 无法跳转到定义
  • 提示路径找不到

需要单独在项目中声明路径映射。

(1)JS 项目: jsconfig.json

在项目根目录创建:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@utils/*": ["./src/utils/*"],
      "@components/*": ["./src/components/*"],
      "@views/*": ["./src/views/*"],
      "@assets/*": ["./src/assets/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

(2)TS 项目: tsconfig.json

compilerOptions 中加入:

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

这样 IDE 和 TS 就能正确解析 @/@utils/ 等路径。

⬆ 返回目录

2.4 常见坑

原因 解决办法
运行正常,IDE 红线 没配置 jsconfig.jsontsconfig.jsonpaths 按上面示例补齐配置
使用 @ 后打包 404 别名写错或路径写错 检查 alias 和实际目录结构
/ 当别名 / 有兼容性问题 不要用 / 做别名

⬆ 返回目录


三、环境变量(env):多环境一把梭

3.1 基本规则

Vite 的环境变量通过 .env 文件管理,有几个重要规则:

  1. 必须加 VITE_ 前缀 才会暴露到前端,否则 import.meta.env.XXX 会是 undefined
  2. 类型都是字符串,需要自己转数字、布尔等
  3. 不要放敏感信息(密钥、token 等),会打包进前端代码

⬆ 返回目录

3.2 文件加载顺序

Vite 会按下面顺序加载,后面的覆盖前面的:

.env                    # 所有模式共用
.env.local              # 所有模式,通常不提交 git
.env.[mode]             # 如 .env.development、.env.production
.env.[mode].local       # 如 .env.development.local

举例:

  • npm run dev → 默认 mode = development,会加载 .env.env.development
  • npm run build → 默认 mode = production,会加载 .env.env.production
  • vite build --mode staging → 会加载 .env.staging

⬆ 返回目录

3.3 完整示例

(1) .env (根目录,所有环境)

# 应用标题
VITE_APP_TITLE=我的 Vue 项目

# API 版本
VITE_API_VERSION=v1

(2) .env.development (开发)

# 开发环境 API 地址
VITE_API_BASE_URL=http://localhost:3000/api

# 是否开启 Mock
VITE_USE_MOCK=true

(3) .env.production (生产)

# 生产环境 API 地址
VITE_API_BASE_URL=https://api.example.com/api

VITE_USE_MOCK=false

(4) .env.staging (预发/测试)

VITE_API_BASE_URL=https://staging-api.example.com/api
VITE_USE_MOCK=false

(5)在代码中使用

// 直接使用
console.log(import.meta.env.VITE_APP_TITLE)
console.log(import.meta.env.VITE_API_BASE_URL)

// 转类型
const useMock = import.meta.env.VITE_USE_MOCK === 'true'
const apiVersion = import.meta.env.VITE_API_VERSION || 'v1'

// 内置变量
if (import.meta.env.DEV) {
  console.log('开发环境')
}
if (import.meta.env.PROD) {
  console.log('生产环境')
}

(6) package.json 脚本

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:staging": "vite build --mode staging",
    "preview": "vite preview"
  }
}

⬆ 返回目录

3.4 TypeScript 类型提示

src/vite-env.d.ts 中声明:

/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_APP_TITLE: string
  readonly VITE_API_BASE_URL: string
  readonly VITE_USE_MOCK: string
  readonly VITE_API_VERSION: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

这样使用 import.meta.env.VITE_* 时会有类型提示和检查。

⬆ 返回目录

3.5 常见坑

原因 解决办法
import.meta.env.XXXundefined 变量名没加 VITE_ 一律用 VITE_ 前缀
修改 .env 不生效 未重启开发服务器 保存后重启 npm run dev
.env 放在 src Vite 只在根目录找 .env 移到项目根
布尔/数字不生效 读出来是字符串 手动转换,如 === 'true'Number()

⬆ 返回目录


四、开发代理(proxy):解决跨域

4.1 为什么需要 proxy?

前端开发在 http://localhost:5173,接口在 http://api.example.com,浏览器会限制跨域请求。

代理的思路是:让 Vite 把 /api 的请求转发到后端,对浏览器来说请求还是同源的。

浏览器 → localhost:5173/api/user → Vite 代理 → api.example.com/user

⬆ 返回目录

4.2 基本配置

// vite.config.js
export default defineConfig({
  server: {
    port: 5173,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

说明:

  • '/api':匹配所有以 /api 开头的请求
  • target:转发到的后端地址
  • changeOrigin: true:把请求头的 host 改成 target,避免目标服务器校验 origin
  • rewrite:请求 /api/user 时,实际转发到 http://localhost:3000/user(去掉 /api

⬆ 返回目录

4.3 结合环境变量

// vite.config.js
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '')
  
  return {
    server: {
      proxy: {
        '/api': {
          target: env.VITE_API_PROXY_TARGET || 'http://localhost:3000',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ''),
          configure: (proxy, options) => {
            proxy.on('proxyReq', (proxyReq, req, res) => {
              console.log(`[Proxy] ${req.method} ${req.url} -> ${options.target}${req.url}`)
            })
          }
        }
      }
    }
  }
})

.env.development 中:

VITE_API_PROXY_TARGET=http://localhost:3000

这样不同环境只需改 .env 即可。

⬆ 返回目录

4.4 多接口代理示例

proxy: {
  '/api': {
    target: 'http://localhost:3000',
    changeOrigin: true,
    rewrite: (path) => path.replace(/^\/api/, '')
  },
  '/upload': {
    target: 'http://localhost:4000',
    changeOrigin: true
  },
  '/ws': {
    target: 'ws://localhost:3001',
    ws: true
  }
}

说明:

  • /api/upload 分别转发到不同端口
  • /wsws: true 支持 WebSocket 代理

⬆ 返回目录

4.5 常见坑

原因 解决办法
代理 404 后端没启动或 target 写错 确认后端服务和地址
生产环境代理无效 proxy 只对开发服务器生效 生产用 Nginx 等做反向代理
目标用 HTTPS 自签名 默认校验证书 secure: false

⬆ 返回目录


五、打包配置(build):控制输出和分块

5.1 常用 build 选项

// vite.config.js
export default defineConfig({
  build: {
    outDir: 'dist',
    assetsDir: 'assets',
    sourcemap: false,
    chunkSizeWarningLimit: 1000,
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js',
        entryFileNames: 'js/[name]-[hash].js',
        assetFileNames: '[ext]/[name]-[hash].[ext]'
      }
    }
  }
})

简要说明:

  • outDir:打包输出目录
  • assetsDir:静态资源子目录
  • sourcemap:是否生成 sourcemap
  • chunkSizeWarningLimit:超过该值(KB)会报警告
  • chunkFileNames / entryFileNames / assetFileNames:控制文件命名和 hash

⬆ 返回目录

5.2 分块策略(manualChunks)

把第三方库和业务代码分开,有利于缓存:

build: {
  rollupOptions: {
    output: {
      manualChunks(id) {
        if (id.includes('node_modules')) {
          if (id.includes('vue') || id.includes('vue-router') || id.includes('pinia')) {
            return 'vue-vendor'
          }
          if (id.includes('axios') || id.includes('lodash')) {
            return 'utils-vendor'
          }
          return 'vendor'
        }
      }
    }
  }
}

这样会生成 vue-vendor-xxx.jsutils-vendor-xxx.jsvendor-xxx.js 等。

⬆ 返回目录

5.3 打包常见坑

原因 解决办法
某个 chunk 超大 大库没被拆分 manualChunks 单独拆出来
部署后资源 404 base 配置不对 子路径部署时设置 base: '/your-app/'
想兼容老浏览器 默认目标较新 设置 build.target: 'es2015'

⬆ 返回目录


六、统一项目配置:一份完整的 vite.config

把 alias、env、proxy、build 整合在一起:

// vite.config.js
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { fileURLToPath } from 'url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '')
  
  return {
    plugins: [vue()],
    base: './',
    
    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src'),
        '@utils': path.resolve(__dirname, './src/utils'),
        '@components': path.resolve(__dirname, './src/components'),
        '@views': path.resolve(__dirname, './src/views'),
        '@assets': path.resolve(__dirname, './src/assets'),
      }
    },
    
    server: {
      port: 5173,
      open: true,
      proxy: {
        '/api': {
          target: env.VITE_API_PROXY_TARGET || 'http://localhost:3000',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, '')
        }
      }
    },
    
    build: {
      outDir: 'dist',
      assetsDir: 'assets',
      sourcemap: false,
      chunkSizeWarningLimit: 1000,
      rollupOptions: {
        output: {
          chunkFileNames: 'js/[name]-[hash].js',
          entryFileNames: 'js/[name]-[hash].js',
          assetFileNames: '[ext]/[name]-[hash].[ext]',
          manualChunks(id) {
            if (id.includes('node_modules')) {
              if (id.includes('vue') || id.includes('vue-router') || id.includes('pinia')) {
                return 'vue-vendor'
              }
              return 'vendor'
            }
          }
        }
      }
    }
  }
})

这样配置后,alias、env、proxy、打包策略都在一处,方便维护和交接。

⬆ 返回目录


七、总结速查

模块 核心点 易错点
alias resolve.alias + jsconfig/tsconfig paths 忘记配 IDE 路径,导致无智能提示
env 变量必须 VITE_ 开头,放根目录 .env 改完不重启、类型当字符串用
proxy 开发时解决跨域,用 changeOrigin 只在 dev 生效,生产需 Nginx 等
build rollupOptions.output 控制分块和命名 basetarget 要按部署和兼容需求设置

建议新项目一开始就把 alias、env、proxy 配好,后面会省很多时间。

如果你有自己踩过的坑,欢迎在评论区补充。

⬆ 返回目录


🔍 系列模块导航

📝 工程化与协作规范

一、《Vite 工程化实战:alias/env/proxy/ 打包配置全解析,统一项目规范避坑|工程化与协作规范篇》
二、《前端多环境配置规范:dev/test/pre/prod 环境差异与配置,避免生产环境踩坑|工程化与协作规范篇》
三、《前端 Git 协作规范实战:commit message + 分支管理 + 合并流程,告别冲突与混乱|工程化与协作规范篇》
四、《ESLint + Prettier 实战:统一前端代码风格,自动修复语法格式问题|工程化与协作规范篇》
五、《Element Plus/VXE-Table UI 组件库规范:统一用法实战,避开样式冲突与维护混乱|工程化与协作规范篇》

👉 跟着系列慢慢学,把技术功底扎扎实实地打牢~

📚 系列总览

前端体系化学习完全体:基础 → 规范 → 架构 → 大厂面试
四套系列、百余篇高质量实战文,从入门到进阶,一站式补齐前端核心能力

每个系列完结后,都会整理成一篇完整导航文并附上直达链接,方便大家按顺序、体系化学习。

全套内容持续更新中,敬请期待~

⬆ 返回目录


技术成长,从来不是比谁写得快,而是比谁写得稳、规范、可维护

哪怕每次只吃透一条规范,长期下来,差距会非常明显。

后续我会持续更新前端规范、工程化、可维护代码相关实战干货,帮你告别面条代码、维护噩梦,在开发与面试中更有底气。

觉得有用欢迎 点赞 + 收藏 + 关注,不错过每一篇实战内容。

我是 Eugene,与你一起写规范、写优质代码,我们下篇干货见~

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐