Vue 3 的 Composition API 和更快的响应式系统让开发体验大幅提升,但一个项目能不能长期健康迭代,靠的不是语法糖,而是工程化体系是否扎实。很多团队在立项时随手 npm create vite 就开干,三个月后面对混乱的目录、失控的依赖体积和各写各风格的代码,才意识到工程化欠下的债迟早要还。这篇文章从脚手架、目录规范、代码质量、构建优化到多环境部署,完整梳理一套可落地的 Vue 3 工程化方案。

脚手架与基础配置:别让默认设置成为天花板
创建项目时,create-vue(官方脚手架)相比直接用 create-vite 的好处在于它会引导你选择 TypeScript、Router、Pinia、ESLint、Prettier 等配套能力,一次性生成完整骨架。对于多人协作的项目,强烈建议直接上 TypeScript,类型约束在跨模块调用时的价值远超初期的学习成本。
生成项目后第一件事是整理 vite.config.ts。默认配置只适合演示,实际项目至少要补齐路径别名、代理、构建分段这几项:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
echarts: ['echarts']
}
}
}
}
})别名用 @ 指向 src 是社区共识,能避免大量 ../../ 式的相对路径。代理配置则解决了本地联调跨域问题,注意 rewrite 的写法要与后端网关约定保持一致,否则会出现本地能跑、测试环境报 404 的经典事故。
另一个容易被忽略的细节是 Node 版本约束。建议在 package.json 中加上 engines 字段,并配合 .npmrc 中的 engine-strict=true,防止团队成员用不兼容的 Node 版本构建出奇怪的产物。
代码规范与目录结构:让协作成本降下来
目录结构没有唯一标准,但必须有标准。一个经过验证的 Vue 3 项目结构大致如下:
src/ ├── api/ # 接口定义,按业务模块拆分 ├── assets/ # 静态资源 ├── components/ # 全局通用组件 ├── composables/ # 组合式函数,useXxx 命名 ├── layouts/ # 布局组件 ├── router/ # 路由与守卫 ├── stores/ # Pinia 模块 ├── styles/ # 全局样式与变量 ├── types/ # TS 类型定义 └── views/ # 页面级组件,按路由组织
规范要落到工具上才有执行力。ESLint 配置推荐使用官方的 eslint-plugin-vue 加上 @typescript-eslint,并把规则接入编辑器实时提示和 Git 提交流程。Husky 加 lint-staged 是最常见的方案:
{
"lint-staged": {
"*.{ts,vue}": ["eslint --fix"],
"*.{css,scss,vue}": ["stylelint --fix"],
"*.{ts,vue,json,md}": ["prettier --write"]
}
}提交阶段只校验暂存区文件,速度快且不会因为历史遗留问题阻塞整个团队。值得一提的是,Vue 3 的 <script setup> 语法配合 ESLint 的 vue/order-in-components-in-setup 类规则,可以把 defineProps、defineEmits、响应式状态、计算属性、方法、生命周期的书写顺序统一起来,review 代码时不用再适应每个人的个性写法。
组合式函数的抽取也要有边界感。判断标准很简单:被两个以上组件复用的逻辑才进 composables,只在一个组件里用的逻辑写在组件内部即可,过度抽象反而增加理解成本。
构建优化与依赖治理:体积是靠盯出来的
Vue 3 默认支持 Tree-shaking,但很多第三方库并不会自动瘦身。比如 Element Plus 这类组件库,必须配合 unplugin-vue-components 做按需自动导入:
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
AutoImport({ resolvers: [ElementPlusResolver()] }),
Components({ resolvers: [ElementPlusResolver()] })
]
}这一步对首屏体积影响非常大,全量引入和按需引入的差距经常超过 500KB。配置完成后,用 rollup-plugin-visualizer 生成体积分析报告,把每个依赖占用的空间可视化出来,谁在偷偷膨胀一目了然。建议把体积分析纳入 CI 流程,构建产物超过阈值就报警,防止依赖劣化悄悄发生。
除了按需引入,还有几项常规优化值得做:路由组件全部改为动态 import() 实现懒加载;图片资源交给构建管线压缩;第三方字体尽量裁剪字重。对于体积特别大的库(如地图 SDK、富文本编辑器),考虑通过 CDN 外置,在 rollupOptions.external 中排除打包,用 vite-plugin-externals 之类的方式挂载全局变量。
多环境配置则交给模式文件管理:.env.development、.env.staging、.env.production 各自维护接口地址等变量,变量统一以 VITE_ 开头,代码中通过 import.meta.env 读取。敏感信息不要进环境文件,部署时由 CI 注入,仓库里只保留占位说明。
工程化不是一次性搭好的架子,而是随项目演进持续打磨的体系。先把脚手架配置、目录规范、提交校验这三件事做扎实,再逐步引入体积监控和构建优化,项目就能在快速迭代中保持秩序,后续无论加人还是加需求,维护成本都可控得多。