Vue 3项目搭建全攻略:从create-vue到Vite工程化实践
创建 Vue 3 项目这件事看起来就是几条命令行的事但真到自己上手敲的时候环境报错、依赖装不上、目录不知道怎么组织这些问题都会跳出来。尤其是从零开始的新手或者以前一直用 Vue 2 的老开发第一次接触 Vite 和组合式 API 的时候还是得花点时间捋一捋。这篇内容就是把我自己搭建 Vue 3 项目时踩过的坑、验证过的方式、以及最终的推荐方案整理出来。无论你是刚入门想跑通第一个 Demo还是在团队里负责初始化和工程化配置这些实际操作的流程和注意点都可以直接参考。1. 创建 Vue 3 项目的三种常见路径1.1 官方脚手架npm create vuelatest现在创建一个 Vue 3 项目最标准的方式是使用官方脚手架create-vue。这个工具由 Vue 官方维护底层绑定的是 Vite 构建工具执行后会通过交互式命令询问你需要的功能模块比如 TypeScript、Vue Router、Pinia、ESLint 等。npm create vuelatest执行这一步时系统会先临时安装create-vue包然后弹出配置选项。如果你不想在命令行里来回选择也可以直接带参数跳过询问npm create vuelatest my-vue3-app -- --typescript --router --pinia注意这里的--typescript、--router、--pinia是功能开关。不同版本的脚手架参数名可能会有细微差异建议先执行不带参数的版本看清楚选项再决定。用官方脚手架有一个明显的好处它生成的模板经过完整的工程化打磨目录结构清晰Vite 配置文件已经预写好ESLint 和 Prettier 的规则也配套完整。对于新项目起步来说这是最稳妥的选择不需要你自己去拼装构建工具链。1.2 轻量方案npm create vite如果你只想快速拿一个干净的空壳项目不想让脚手架帮你创建路由、状态管理这些文件那直接用 Vite 自带的创建命令就够了npm create vitelatest my-vite-app -- --template vue或者选择 Vue 的 TypeScript 模板npm create vitelatest my-vite-app -- --template vue-ts这种方式创建出来的项目非常精简只包含 Vite 的基础配置和src/main.js、App.vue等核心文件。路由、状态管理、UI 组件库全部由你自己按需添加。好处是灵活坏处是后续的集成工作都得自己来。如果你是想深入学习 Vue 3 的工程化结构或者准备在项目里定制特殊的目录规范推荐用这个方案。1.3 直接在 HTML 里引入还有一条路不需要任何构建工具直接用 CDN 方式在 HTML 里引入 Vue。script srchttps://unpkg.com/vue3/dist/vue.global.js/script div idapp{{ message }}/div script const { createApp, ref } Vue; createApp({ setup() { const message ref(Hello Vue 3); return { message }; } }).mount(#app); /script这种方式适合快速验证 API、做简单的静态页面 Demo或者在不方便搭建 node 环境的机器上做演示。但生产环境不推荐因为少了编译打包的环节语法上很难直接用单文件组件SFC组件化开发基本无从谈起。1.4 三种方式该怎么选方式适用场景上手成本后续扩展成本npm create vuelatest正规项目、团队协作、需要完整工程链低全程问答式低模板自带主流配置npm create vitelatest学习研究、轻量起步、自定义工程结构低命令简单中路由、状态管理需自行接入CDN 直接引入快速验证、单页面 Demo极低极高不适合完整项目2. 为什么推荐 Vite 作为构建工具2.1 Vite 相比 Webpack 的优势Vue 3 官方推荐的构建工具是 Vite而不是 Vue 2 时代常用的 Webpack。核心原因是 Vite 在开发服务器启动速度上有着肉眼可见的差别。传统 Webpack 启动时需要先扫描全部依赖、预编译所有模块而 Vite 利用浏览器原生 ES Module 支持启动时只处理当前页面实际需要的模块冷启动速度远快于 Webpack。另一个实用场景是热更新。Vite 的 HMR热模块替换是基于模块依赖关系做局部更新改一个组件模板基本瞬间反映到页面上不需要刷新整个页面。这在调整组件样式、调试业务逻辑时体验差别非常明显。2.2 Vite 的生态兼容性Vite 对 Vue 3 的支持是原生级别的官方提供的vitejs/plugin-vue插件可以直接处理.vue单文件组件的编译。配合vue-tsc可以做 TypeScript 的类型检查配合vite-plugin-eslint可以在编译阶段检查代码风格整个工程链比较完善。而且 Vite 的强大之处在于不挑框架。同一个工程里你写 Vue、React、原生 JS 都没问题通过不同的插件支持即可。所以哪怕团队里同时存在多个技术栈的项目Vite 的学习经验也可以直接复用。3. 实操一次完整搭建一个 Vue 3 项目3.1 检查 Node.js 环境搭建之前第一件事是确认 Node.js 环境。Vite 5 版本对 Node 版本的硬性要求是 18 或 20如果你还在用 Node 16创建项目时会直接收到警告甚至无法安装依赖。node -v npm -v如果版本太低建议先升级。不需要纠结装多新的版本通常当前 LTS 版本就是最稳的。升级 Node.js 的方式很多Windows 上直接重新安装即可macOS 推荐用 nvm 管理不同版本方便多个项目切换。这个细节值得在意。很多人在创建项目时反复报错查到最后都是 Node 版本兼容性问题。Vite 内部使用的是现代 JavaScript 语法旧版本运行时可能出现各种怪异的行为。3.2 使用 create-vue 初始化项目执行npm create vuelatest按照提示输入项目名称确认功能模块。我比较常用的选项组合是 TypeScript Vue Router Pinia ESLint Prettier前几个项目直接搭好后续不用重复接。如果你是第一次使用 TypeScript建议稍微多花一点时间了解它的基础语法。Vue 3 的script setup配合 TypeScript 是官方推荐的组合写起来并不复杂接口定义、泛型约束这些在业务代码里慢慢积累就够了。3.3 安装依赖与启动开发服务器cd my-vue3-app npm install npm run devnpm run dev执行后终端会输出一个本地访问地址默认是http://localhost:5173/。如果这个端口被占用Vite 会自动递增为 5174、5175不需要手动处理。首次启动时看到如下的输出说明环境已经跑通了VITE v5.0.0 ready in 235 ms ➜ Local: http://localhost:5173/ ➜ Network: http://192.168.1.100:5173/3.4 项目目录结构认识第一次运行成功后建议先花十分钟熟悉整个项目结构。以 create-vue 生成的模板为例重点文件说明如下├── index.html # 入口 HTML 文件 ├── src/ │ ├── main.ts # 应用入口创建 Vue 实例 │ ├── App.vue # 根组件 │ ├── components/ # 自定义组件存放目录 │ ├── router/index.ts # 路由配置 │ ├── stores/ # Pinia 状态管理 │ ├── views/ # 视图组件 │ └── assets/ # 静态资源 ├── vite.config.ts # Vite 构建配置 ├── package.json # 依赖与脚本 └── tsconfig.json # TypeScript 配置理解这个结构的意义在于后续所有的业务代码都会按照这套约定来组织。团队协作时只要都遵循同一套目录规范开发中就能很快找到对应的修改位置。3.5 添加一个简单页面流程创建src/components/HelloWorld.vuescript setup langts import { ref } from vue; const count ref(0); /script template div h1Hello Vue 3/h1 button clickcount计数{{ count }}/button /div /template style scoped button { padding: 8px 16px; border-radius: 6px; } /style然后在App.vue中引入它script setup langts import HelloWorld from ./components/HelloWorld.vue; /script template HelloWorld / /template保存文件后页面会自动更新。如果你把HelloWorld.vue里的内容改掉比如把button的文案改了浏览器里能即刻看到变化。这个即时反馈机制就是 Vite HMR 的作用也是开发效率提升最明显的地方。3.6 加入路由和状态管理create-vue 创建时如果选择了 Vue Router那么src/router/index.ts已经被生成只需要在里面增加路由记录即可import { createRouter, createWebHistory } from vue-router; import HomeView from ../views/HomeView.vue; const router createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: /, name: home, component: HomeView }, { path: /about, name: about, component: () import(../views/AboutView.vue) } ] }); export default router;第二段路由用了动态导入的写法。这种写法会让 Vite 在构建时自动做代码分割把AboutView单独打包成一个 chunk只有当访问/about路径时才会加载该文件有助于缩小首屏包体积。状态管理部分Pinia 的接入也很简单import { createPinia } from pinia; import { createApp } from vue; import App from ./App.vue; const app createApp(App); app.use(createPinia()); app.mount(#app);4. 搭建过程中的常见报错与避坑要点4.1 npm install 长期卡住或报错 ERR! code ERESOLVE这个报错通常在依赖版本冲突时出现。解决方案有两种一是检查是否存在.npmrc文件里配置了不正确的 registry二是在 install 命令后面加上--legacy-peer-deps临时绕过依赖冲突。npm install --legacy-peer-deps如果项目里一直需要这个参数可以在项目根目录的.npmrc中配置legacy-peer-depstrue但要注意这只是绕过而非解决冲突。建议平时安装依赖时保持主要依赖库的版本尽量接近官方最新稳定版减少这种问题的出现概率。4.2 命令行提示 node: internal/modules/cjs/loader 错误出现这类错误绝大多数情况是 Node 版本问题。建议切换到 LTS 稳定版然后删除 node_modules 重新安装rm -rf node_modules package-lock.json npm install如果你用 nvm 管理多个 Node 版本还要注意切换后确认当前生效的版本是否正确。4.3 Vite 端口被占用默认 5173 端口被占用时Vite 会自动选择 5174这个机制比较友好一般不需要手动干预。如果希望指定端口可以在项目根目录下创建.env文件VITE_PORT8080或者修改vite.config.tsexport default defineConfig({ server: { port: 8080, strictPort: true } });strictPort设为true时如果指定端口被占用Vite 会直接报错而不是自动切换端口方便在固定的开发环境里保持一致。4.4 页面空白且控制台没有报错遇到过好多次页面打开是空白的刷新一下又好了控制台什么错误都没有。这种情况优先查路由模式如果你使用的是createWebHistory模式需要后端做对应的 history fallback如果部署环境不支持改用 hash 模式import { createWebHashHistory } from vue-router; const router createRouter({ history: createWebHashHistory(), routes: [...] });不过本地开发一般不会遇到这个问题更多是打包部署到测试环境后才出现。4.5 Vite 代理配置解决跨域开发环境中调用后端接口最常见的就是跨域问题。Vite 的解决办法是在vite.config.ts中配置代理export default defineConfig({ server: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } } });这样前端代码里请求/api/user/info时Vite 会把请求转发到http://localhost:3000/user/info并且通过changeOrigin把请求头中的 host 修改为目标地址从根源上规避了开发环境的跨域限制。生产环境跨域问题则需要后端配合设置 CORS 头那是另一个问题了。4.6 组件文件命名细节单文件组件建议使用大驼峰命名法比如UserProfile.vue而不是userProfile.vue。倒不是说小驼峰一定会报错而是 PascalCase 在模板中引用更规范能避免与原生 HTML 标签产生大小写混淆的问题。比如user-profile这种横线连接方式在某些场景下可能会被误判但UserProfile引用起来就明确多了。5. 关于 Vue 3 初始化时的工程化配置建议5.1 使用 pnpm 替代 npm如果你还没有固定使用某种包管理器我建议试试 pnpm。它在安装依赖时的磁盘占用更小、安装速度更快同时对 monorepo 的支持也更完善。创建项目后只用三条命令即可启动pnpm install pnpm dev换成 pnpm 不需要额外配置什么项目根目录锁文件用pnpm-lock.yaml团队协作时确保大家都用 pnpm 即可。这样做的受益在依赖数量较多的项目中尤其明显。5.2 明确别名配置项目创建后第一件事建议把路径别名配好避免深层次目录出现../../../这种情况。在vite.config.ts中配置import path from node:path; export default defineConfig({ resolve: { alias: { : path.resolve(__dirname, src) } } });同时需要同步修改tsconfig.json{ compilerOptions: { baseUrl: ., paths: { /*: [src/*] } } }这样之后所有导入都能写成import UserProfile from /components/UserProfile.vue;在大型项目里这个细节会直接影响日常开发体验。早配早舒服。5.3 配置模块路径别名的两个小坑第一个坑是vite.config.ts里直接使用__dirname可能会在 ESM 环境下报未定义。解决办法是import { fileURLToPath, URL } from node:url; export default defineConfig({ resolve: { alias: { : fileURLToPath(new URL(./src, import.meta.url)) } } });第二个坑是改了别名后IDE 仍然找不到路径提示。这时需要重启 TypeScript 服务在 VSCode 里按下Ctrl Shift P输入TypeScript: Restart TS Server问题通常就能解决。5.4 开发依赖和生成式依赖分开管理安装依赖时想清楚哪些放在dependencies哪些放在devDependencies。dependencies运行时必须用到的库比如vue、vue-router、pinia、UI 组件库。devDependencies构建时和开发时用到的工具比如vite、vitejs/plugin-vue、eslint、typescript。如果库的体积较大且只在开发阶段使用误放到dependencies里最终构建产物的体积就会变大。所以养成习惯安装时指定参数。npm install element-plus # 运行时依赖 npm install -D sass # 开发依赖这个习惯虽然基础但能避免不少后期性能优化时的头疼问题。5.5 环境变量管理Vite 项目里区分三种环境文件.env # 所有环境共享 .env.development # 开发环境 .env.production # 生产环境变量名必须以VITE_开头才能在代码中暴露出比如VITE_API_BASE_URL。在代码中通过import.meta.env.VITE_API_BASE_URL访问。这个设计是为了避免把服务端密钥等信息误暴露到客户端代码中。凡是需要保密的配置永远不要放在环境文件中提交到仓库。含敏感信息的本地配置应放在.env.local中并且该文件应加入.gitignore。6. 实际使用中的一些补充想法在我实际操作中有一个始终不变的建议创建项目后先提交一次 Git把脚手架生成的初始状态固定下来。之后再做任何配置修改、依赖安装、结构调整每一步都可以单独提交。这个方法在团队协作和问题回溯时省了很多时间。有一次 A 同学配置了 ESLint 后出现全量报错我们直接用 Git diff 对比出配置差异两分钟内就定位了问题这种场景很常见。另外在创建项目时选择功能模块别贪多。没有明确需求时路由和状态管理可以先装着但像 Vitest、端到端测试这些完全可以后续需要时再接。初始模板越乱上手的迷惑感越强。加功能永远比删功能简单这个原则从项目初始化一直延续到组件设计都是这样。Vue 3 项目搭建本身并不复杂复杂的是搭建完后如何有序地扩展和维护。脚手架的交互式选项虽然帮我们做了大部分决策但工程化的细节还得靠日常积累。我上面写到的这些内容希望能够帮你避开初级阶段的那些常见问题快速进入实际业务开发。