导读:本期聚焦于梧桐创作的《Vue 3 项目工程化如何搭建?从脚手架到构建部署的完整实践》,敬请观看详情。为什么同样是用 Vue 3 写页面,有的团队项目越做越乱,有的团队却能把代码规范、构建速度、类型检查、按需引入和自动化部署都安排得井井有条?答案往往不在框架本身,而在工程化的搭建水平。本文围绕 Vue 3 的工程化实践展开,先从 Vite 创建项目讲起,分析目录结构设计、别名配置与环境变量管理的做法,再介绍 ESLint 与 Prettier 如何配合统一代码风格,接着讲解 TypeScript 在 Vue 3 中的接入要点与常见坑,最后讨论自动按需导入、打包分析与 CI 部署等环节,帮你把一个普通的前端项目改造成可持续维护的标准化工程。

Vue 3 的 Composition API 和响应式系统重构让框架本身的性能和开发体验都上了一个台阶,但框架只能解决写代码的问题,解决不了代码怎么组织、规范怎么统一、构建怎么提速这些事。这些恰恰是工程化要干的活。一个没有做工程化治理的 Vue 3 项目,通常在三个月后就会暴露出目录混乱、依赖冲突、类型报错满天飞的问题。本文把 Vue 3 工程化搭建的完整流程拆开讲清楚,从项目初始化一路讲到构建部署。

Vue 3 项目工程化如何搭建?从脚手架到构建部署的完整实践

一、项目初始化与目录结构设计

官方推荐用 Vite 来创建 Vue 3 项目,执行 npm create vue@latest 后会进入交互式引导,可以按需勾选 TypeScript、Router、Pinia、ESLint、Prettier 等选项。相比手动搭脚手架,这种方式生成的项目已经预置好了 vite.config.ts、TS 配置和基础目录。如果追求极简,也可以用 npm create vite@latest my-app -- --template vue-ts 直接落成一个最小化的 TS 模板。

目录结构没有绝对标准,但要遵循一条原则:按职责分层,而不是按文件类型堆砌。推荐的结构大致如下:

src/
├── api/          # 接口请求,按业务模块拆分文件
├── assets/       # 静态资源
├── components/   # 通用组件
├── composables/  # 组合式函数,useXxx 命名
├── layouts/      # 布局组件
├── router/       # 路由配置
├── stores/       # Pinia 仓库
├── styles/       # 全局样式与变量
├── types/        # TS 类型定义
├── utils/        # 工具函数
├── views/        # 页面级组件
├── App.vue
└── main.ts

把组合式函数单独放进 composables 目录是 Vue 3 项目的惯例,凡是跨页面复用的逻辑,比如分页请求、防抖搜索、权限校验,都应该抽成 useXxx 形式的函数,而不是塞进 mixins。Mixins 在 Vue 3 中已被官方明确不推荐,命名冲突和来源不透明的老问题在大型项目里会被无限放大。

路径别名也是初始化阶段就该配好的。在 vite.config.ts 中设置别名之后,import 语句就不用再写一长串相对路径,重构移动文件时也不用逐个修改引用:

import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  server: {
    port: 5173,
    proxy: {
      // 本地开发代理,解决跨域
      '/api': {
        target: 'http://127.0.0.1:3000',
        changeOrigin: true
      }
    }
  }
})

注意别名要在 tsconfig.json 里同步配置 paths 字段,否则 Vite 能编译通过,但 IDE 的类型提示会报找不到模块。

二、代码规范与提交规范治理

多人协作的项目里,规范不统一是最消耗精力的事。工程化的做法是把规范固化到工具链里,让代码在提交前自动被检查和格式化。核心组合是 ESLint 负责代码质量检查,Prettier 负责格式统一,husky 加 lint-staged 负责在 git 提交钩子上强制执行前两者。

Vue 3 项目推荐直接使用官方的 @vue/eslint-config-typescript 配置集,它已经处理好了 .vue 单文件组件中 script 部分的解析问题。一份典型的基础配置如下:

import pluginVue from 'eslint-plugin-vue'
import vueTsEslintConfig from '@vue/eslint-config-typescript'

export default [
  ...pluginVue.configs['flat/recommended'],
  ...vueTsEslintConfig(),
  {
    rules: {
      'vue/multi-word-component-names': 'off',
      '@typescript-eslint/no-explicit-any': 'warn'
    }
  }
]

接下来装上 husky 和 lint-staged,配置在 package.json 中:

{
  "lint-staged": {
    "*.{ts,tsx,vue}": ["eslint --fix", "prettier --write"],
    "*.{css,scss,json,md}": ["prettier --write"]
  }
}

这样配置之后,任何不规范或未格式化的代码都无法通过 git commit,规范从口头约定变成了流程约束。再进一步可以引入 commitlint 约束提交信息格式,要求提交说明必须符合 featfixdocs 这类前缀,方便后续生成变更日志和版本号。

三、TypeScript 接入要点与常见坑

Vue 3 对 TypeScript 的支持是原生级别的,<script setup lang="ts"> 写法下,ref、computed、props 都能获得完整类型推导。但有几个坑值得提前知道。

第一个坑是 ref 的类型收窄。ref(1) 会被推导成 Ref<number>,这是对的,但如果初始值是 null,比如获取 DOM 引用时写 ref(null),类型就成了 Ref<null>,后续赋值会报错。正确做法是显式标注泛型:

import { ref } from 'vue'

// 错误:类型被推导为 Ref<null>
const box = ref(null)

// 正确:显式指定联合类型
const inputEl = ref<HTMLInputElement | null>(null)

第二个坑是 defineProps 的类型写法。在 <script setup> 中推荐直接用类型参数声明 props,编译宏会自动生成运行时校验:

<script setup lang="ts">
interface Props {
  title: string
  count?: number
  list: string[]
}

const props = withDefaults(defineProps<Props>(), {
  count: 0
})
</script>

第三个坑是第三方库的类型缺失。有些老库没有自带类型声明,直接 import 会报 TS 错误。可以在 types 目录下写一个 .d.ts 文件声明模块,或者临时用 declare module 兜底,但长期方案还是优先选择有类型维护的替代库。

接口返回值的类型也不该放任不管。建议在 types 目录里按业务定义响应结构,并封装统一的请求函数把后端返回解析成具体类型,这样组件里拿到的数据全程有类型提示,字段写错在编码阶段就会被标红。

四、构建优化与自动化部署

开发到一定规模后,构建产物的体积和依赖的加载方式需要专门治理。Element Plus 这类大型组件库如果全量引入,会把包体积撑大不少,配合 unplugin-vue-components 可以实现模板中用到哪个组件就自动按需引入哪个,无需手动注册:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ],
  build: {
    rollupOptions: {
      output: {
        // 按需拆包,利用浏览器缓存
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
          echarts: ['echarts']
        }
      }
    }
  }
})

拆分 manualChunks 的意义在于业务代码频繁变动时,vendor 这类稳定依赖的缓存不会失效,用户二次访问能直接命中浏览器缓存,加载速度明显改善。拆分粒度也不宜过细,几十 KB 的小包反而会增加请求数。配好之后可以用 rollup-plugin-visualizer 生成体积分析报告,直观看到每个依赖占了多少空间,再决定优化目标。

部署环节建议交给 CI 流水线。以常见的方案为例,推送代码到仓库后自动触发流水线:安装依赖、执行类型检查和单元测试、跑生产构建、把 dist 目录发布到静态服务器或 CDN。package.json 里准备好脚本即可:

{
  "scripts": {
    "dev": "vite",
    "build": "run-p type-check build-only",
    "type-check": "vue-tsc --noEmit",
    "build-only": "vite build",
    "lint": "eslint . --fix"
  }
}

vue-tsc --noEmit 做纯类型检查放在构建流程里,能在打包前拦住类型错误,避免把带病代码发上线。环境变量方面记得遵守 Vite 的约定:只有 VITE_ 前缀的变量会暴露给客户端代码,密钥类信息绝对不要写进 .env 文件,而是留在构建环境的私密变量里注入。

总结一下,Vue 3 的工程化本质上是一套流水线:Vite 负责构建效率,目录结构与组合式函数负责代码组织,ESLint 与 Prettier 负责规范统一,TypeScript 负责类型安全,按需加载与分包负责产物优化,CI 负责部署自动化。每个环节单独看都不复杂,串起来之后项目的可维护性会有质的提升,团队新人接手时也能快速找到代码的正确位置,这才是工程化真正的价值所在。

Vue 3工程化Vite配置TypeScript修改时间:2026-09-03 19:43:20

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260903/49768.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。