从零搭建Vue 3项目:IDEA实战与工程化配置指南

📅 2026/8/6 20:01:55
从零搭建Vue 3项目:IDEA实战与工程化配置指南
1. 为什么需要从零开始搭建Vue 3项目如果你刚开始接触Vue 3可能会觉得直接用官方的create-vue脚手架或者Vite模板生成项目是最快、最省事的选择。这没错对于快速启动一个标准项目它们非常高效。但作为一个有经验的开发者我强烈建议你至少亲手用IDEAIntelliJ IDEA完整地搭建一次项目。这个过程的价值远不止于得到一个能运行的工程。首先它能让你彻底摆脱“黑盒”的依赖。当项目出现一个诡异的构建错误或者你需要集成一个非主流的库时如果你对项目底层的Webpack或Vite配置、依赖关系、脚本命令一无所知排查问题会异常痛苦。亲手搭建的过程就是一次对现代前端工程化核心链条的深度遍历从包管理工具npm/yarn/pnpm的选择到构建工具Vite的配置再到代码规范工具ESLint, Prettier的集成每一步你都需要做出选择并理解其背后的原因。其次它能帮你建立最适合自己或团队的技术栈“配方”。官方的模板提供了良好的起点但未必完全契合你的需求。比如你可能需要特定的UI库如Element Plus、状态管理库Pinia、路由方案Vue Router的特定版本组合或者一些特殊的构建优化。通过自定义搭建你可以像搭积木一样按需引入和配置形成一个高度定制化、可复用的项目种子。下次启动类似项目时你完全可以基于这个自定义的模板快速初始化效率反而会更高。最后对于使用IDEA这类强大IDE的开发者来说手动搭建能让你更好地利用IDE的功能。IDEA对JavaScript和Vue的支持非常出色但一些高级功能如智能提示、代码检查、运行配置需要正确的项目结构和配置文件才能完美工作。自己搭建意味着你清楚地知道每个配置文件vite.config.ts,tsconfig.json,.eslintrc.js的位置和作用能更精准地配置IDE以获得最佳开发体验。所以这篇内容不是简单地重复官方文档的步骤而是结合我多次搭建企业级Vue 3项目的经验带你走一遍“思考-选择-实施-优化”的完整路径。我们会从最纯粹的空文件夹开始一步步构建出一个功能完备、配置清晰、便于团队协作的Vue 3项目骨架。2. 前期核心决策工具链选型与思考在动手敲命令之前有几个关键决策需要先确定下来。这些选择将贯穿整个项目生命周期影响开发效率和最终产物的质量。2.1 包管理工具npm, yarn 还是 pnpm这是一个看似简单却影响深远的选择。三者都是优秀的包管理工具但特性不同。npmNode.js 自带无需额外安装生态最广。但其早期版本的依赖安装速度和磁盘空间占用常被诟病。新版本v7引入了package-lock.jsonv2和更好的依赖提升算法性能已有很大改善。如果你的团队追求最少的工具依赖和最高的兼容性npm是稳妥的选择。yarn由Facebook推出以其确定性的依赖安装通过yarn.lock和更快的下载速度早期优势闻名。yarn 2Berry带来了颠覆性的PlugnPlay(PnP) 特性能进一步提升安装速度和解决“node_modules黑洞”问题但生态兼容性上需要更多考量。pnpm近年来势头很猛它采用“内容寻址存储”和“符号链接”的方式管理依赖。这是我最推荐用于新项目的工具。它的核心优势在于极致的磁盘空间节省所有依赖包在全局store中只存储一份项目通过硬链接引用对于同时维护多个大型前端项目的开发者来说这是福音。更快的安装速度得益于其独特的存储和链接机制安装速度通常比npm和yarn快很多。严格的依赖结构默认使用非扁平化的node_modules结构能有效避免“幽灵依赖”即使用了一个未在package.json中声明的包的问题让依赖关系更清晰、更安全。我的选择与理由对于全新的Vue 3项目我会优先选择pnpm。它不仅性能优越其严格的依赖管理也能从项目初期就培养良好的依赖声明习惯减少未来潜在的依赖冲突风险。后续的步骤都将基于pnpm进行演示。如果你选择npm或yarn大部分命令只需做简单替换如pnpm add对应npm install或yarn add。2.2 构建工具为什么是 ViteVue 3官方推荐使用Vite作为构建工具这绝非偶然。与传统的Webpack相比Vite在开发体验上带来了质的飞跃。基于原生ESM的极速服务启动Vite在开发模式下不需要打包整个应用而是直接利用浏览器对ES模块的原生支持。当你启动开发服务器时Vite只会启动一个轻量级的服务器然后根据浏览器的请求按需编译和返回源码。这意味着无论你的应用有多大启动时间都几乎是瞬间完成的。超快的热更新HMR同样得益于ESM当某个模块被修改时Vite只需精确地使该模块的链失效然后进行即时更新速度极快几乎感觉不到延迟。开箱即用的优秀体验Vite对TypeScript、JSX、CSS预处理器Sass, Less等都有内置支持无需复杂配置。其构建优化如异步块加载、CSS代码分割也做得很好。虽然Webpack功能无比强大且生态成熟但对于大多数Vue 3项目而言Vite在开发效率上的优势是决定性的。因此我们的项目将基于Vite搭建。2.3 编程语言JavaScript 还是 TypeScript这是一个关于项目长期可维护性的选择。TypeScript为JavaScript提供了静态类型检查能在编码阶段就捕获大量潜在的错误如拼写错误、调用未定义的方法、参数类型不匹配等极大地提升了代码的健壮性和开发体验尤其是在团队协作中。Vue 3本身就是用TypeScript编写的对TS的支持是一流的。使用TypeScript开发Vue 3项目可以获得完美的组件Props、Emits、Refs等的类型推断和智能提示。我的强烈建议除非项目非常小或是快速原型否则一律选择TypeScript。初期多花一点时间学习类型定义会在项目的中后期为你节省大量的调试时间和心智负担。IDEA对TypeScript的支持也是顶级的能提供无与伦比的代码补全和错误提示。2.4 代码规范与格式化ESLint Prettier一个统一的代码风格是团队协作的基石。我们将集成这两大工具ESLint用于识别和报告JavaScript/TypeScript代码中的模式问题目标是保证代码质量和避免错误。例如它可以检查未使用的变量、使用而非等。Prettier一个“有主见”的代码格式化工具。它只关心代码格式如缩进、分号、引号、行长等并强制将其格式化为统一的风格。将格式化的任务交给Prettier可以避免团队成员在代码风格上的无谓争论。我们将配置它们协同工作ESLint负责代码质量规则Prettier负责风格规则并通过插件避免两者冲突。3. 实战在IDEA中一步步搭建项目现在让我们打开IntelliJ IDEA开始动手。3.1 初始化项目与基础结构创建空项目打开IDEA选择“New Project”。在左侧列表中选择“Empty Project”为项目命名例如my-vue3-app并选择存放位置点击“Create”。初始化包管理在IDEA底部打开“Terminal”终端。首先确保你安装了Node.js建议版本16。然后初始化项目并创建package.json文件。# 如果你选择pnpm推荐 pnpm init # 如果你选择npm npm init -y # 如果你选择yarn yarn init -y执行后项目根目录会生成一个package.json文件。安装Vue 3和Vite我们将安装Vue 3的核心库以及Vite作为开发依赖。# 使用pnpm pnpm add vue pnpm add -D vite vitejs/plugin-vue # 使用npm npm install vue npm install -D vite vitejs/plugin-vue # 使用yarn yarn add vue yarn add -D vite vitejs/plugin-vuevue: Vue 3核心库。vite: 构建工具。vitejs/plugin-vue: Vite官方提供的Vue插件用于解析.vue单文件组件。创建基础目录与文件在项目根目录下手动创建以下结构和文件my-vue3-app/ ├── index.html # 应用入口HTML ├── vite.config.ts # Vite配置文件 ├── tsconfig.json # TypeScript配置文件 ├── src/ │ ├── main.ts # 应用入口JS/TS文件 │ ├── App.vue # 根组件 │ ├── components/ # 存放通用组件 │ └── assets/ # 存放静态资源 └── public/ # 纯静态资源不会被Vite处理3.2 配置核心文件接下来我们来填充这些核心配置文件的内容。1.index.html(应用入口)!DOCTYPE html html langzh-CN head meta charsetUTF-8 / link relicon typeimage/svgxml href/vite.svg / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title我的Vue 3应用/title /head body div idapp/div !-- 注意这里引入的是 /src/main.tsVite会处理它 -- script typemodule src/src/main.ts/script /body /html关键点div idapp是Vue应用挂载的根节点。script typemodule src/src/main.ts使用原生ES模块方式引入入口文件Vite服务器会处理这个请求。2.src/main.ts(应用入口JS)import { createApp } from vue import App from ./App.vue createApp(App).mount(#app)这是Vue 3应用的标准启动方式从vue导入createApp工厂函数传入根组件App.vue然后将其挂载到HTML中id为app的元素上。3.src/App.vue(根组件)template div h1你好Vue 3 Vite TypeScript/h1 p这是一个自定义搭建的项目。/p /div /template script setup langts // 这是一个使用 script setup 语法的组件 // langts 启用了 TypeScript 支持 /script style scoped /* scoped 使样式仅作用于当前组件 */ h1 { color: #42b983; } /style这里我们使用了Vue 3的script setup语法糖它是一种编译时语法让组合式API的写法更简洁。langts表明我们使用TypeScript。style scoped表示这里的CSS样式只作用于当前组件。4.vite.config.ts(Vite配置)import { defineConfig } from vite import vue from vitejs/plugin-vue import { resolve } from path // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], resolve: { alias: { : resolve(__dirname, src) // 设置 指向 src 目录 } }, server: { port: 3000, // 设置开发服务器端口 open: true, // 启动后自动打开浏览器 host: true // 监听所有地址方便局域网内其他设备访问如手机调试 } })plugins: 注册Vite插件这里只用了Vue插件。resolve.alias: 配置路径别名。将映射到src目录这样在代码中就可以用/components/Hello.vue来代替相对路径../components/Hello.vue更清晰且不易出错。server: 开发服务器配置。我习惯设置固定端口、自动打开并开启host以便真机调试。5.tsconfig.json(TypeScript配置){ compilerOptions: { target: ES2020, useDefineForClassFields: true, module: ESNext, lib: [ES2020, DOM, DOM.Iterable], skipLibCheck: true, /* Bundler mode */ moduleResolution: bundler, allowImportingTsExtensions: true, resolveJsonModule: true, isolatedModules: true, noEmit: true, jsx: preserve, /* Linting */ strict: true, noUnusedLocals: true, noUnusedParameters: true, noFallthroughCasesInSwitch: true, /* Path Alias */ baseUrl: ., paths: { /*: [src/*] } }, include: [src/**/*.ts, src/**/*.d.ts, src/**/*.tsx, src/**/*.vue], references: [{ path: ./tsconfig.node.json }] }这个配置继承了Vite官方TS模板的推荐设置关键点包括strict: true开启所有严格的类型检查。paths配置路径别名以匹配Vite中的设置让TypeScript能正确解析/导入。include指定TypeScript需要处理的文件范围包含了.vue文件。还需要创建一个tsconfig.node.json用于Vite自身的TS配置通常不需要修改{ compilerOptions: { composite: true, skipLibCheck: true, module: ESNext, moduleResolution: bundler, allowSyntheticDefaultImports: true, strict: true }, include: [vite.config.ts] }3.3 配置开发脚本与首次运行回到package.json我们需要添加一些脚本命令。{ name: my-vue3-app, private: true, version: 0.0.0, type: module, scripts: { dev: vite, build: vue-tsc vite build, preview: vite preview }, dependencies: { vue: ^3.4.0 }, devDependencies: { vitejs/plugin-vue: ^5.0.0, vite: ^5.0.0 } }type: module: 声明项目使用ES模块。scripts:dev: 启动开发服务器。build: 构建生产版本。vue-tsc是一个命令行工具用于对.vue文件进行TypeScript类型检查确保构建前的代码类型安全。preview: 预览构建后的产物本地静态服务器。现在在终端运行pnpm dev # 或 npm run dev, yarn dev如果一切顺利终端会显示Local: http://localhost:3000/并且浏览器会自动打开显示“你好Vue 3 Vite TypeScript”。第一个实操心得如果遇到端口被占用Vite会提示并询问是否使用另一个端口。你也可以在vite.config.ts的server.port中预先修改。如果遇到Cannot find module vue之类的错误请检查node_modules是否存在并确保终端当前路径在项目根目录下。4. 增强项目集成必备开发工具链一个基础项目能跑了但离“好用”还差得远。接下来我们集成代码规范、路由和状态管理这些提升开发体验和项目结构的利器。4.1 集成 ESLint Prettier TypeScript安装依赖这是一组比较多的开发依赖。pnpm add -D eslint eslint-plugin-vue typescript-eslint/parser typescript-eslint/eslint-plugin prettier eslint-config-prettier eslint-plugin-prettier vue/eslint-config-typescripteslint: ESLint核心。eslint-plugin-vue: Vue.js的ESLint插件。typescript-eslint/parsertypescript-eslint/eslint-plugin: 用于解析和检查TypeScript代码。prettier: Prettier核心。eslint-config-prettiereslint-plugin-prettier: 用于整合ESLint和Prettier避免规则冲突。vue/eslint-config-typescript: Vue官方提供的TypeScript ESLint配置。创建配置文件.eslintrc.cjs(ESLint配置)module.exports { root: true, env: { browser: true, es2021: true, node: true, }, extends: [ plugin:vue/vue3-essential, // Vue 3基础规则 eslint:recommended, // ESLint推荐规则 vue/eslint-config-typescript, // Vue TS规则 plugin:prettier/recommended, // 将Prettier规则集成进ESLint ], parserOptions: { ecmaVersion: latest, parser: typescript-eslint/parser, sourceType: module, }, plugins: [vue, typescript-eslint], rules: { // 可以在这里覆盖或添加自定义规则 vue/multi-word-component-names: off, // 关闭组件名必须多单词的规则 }, }.prettierrc(Prettier配置){ semi: false, // 句尾不加分号 singleQuote: true, // 使用单引号 trailingComma: es5, // 在ES5中有效的尾随逗号对象、数组等 printWidth: 100, // 每行代码长度 tabWidth: 2, // 缩进空格数 useTabs: false // 使用空格缩进 }.eslintignore.prettierignore(忽略文件)node_modules dist *.local .DS_Store配置IDEA为了让IDEA自动使用这些工具需要进行设置。启用ESLint打开File - Settings - Languages Frameworks - JavaScript - Code Quality Tools - ESLint。勾选Manual ESLint configuration指定配置文件路径.eslintrc.cjs并勾选Run eslint --fix on save。启用Prettier打开File - Settings - Languages Frameworks - JavaScript - Prettier。选择Prettier package通常IDEA会自动检测到node_modules中的prettier。关键一步在On code reformat和On save的选项中建议勾选On code reformat这样当你使用CtrlAltL(Win/Linux) 或CmdOptionL(Mac) 格式化代码时会使用Prettier规则。你也可以勾选On save实现保存时自动格式化。现在当你写代码时ESLint会实时提示错误和警告保存或格式化时Prettier会自动调整代码风格。4.2 集成 Vue Router 和 PiniaVue Router用于页面路由Pinia是Vue 3官方推荐的状态管理库比Vuex更简洁、类型安全。安装pnpm add vue-router pinia配置Vue Router在src下创建router/index.ts文件。import { createRouter, createWebHistory } from vue-router // 定义路由组件这里使用懒加载优化首屏 const Home () import(/views/Home.vue) const About () import(/views/About.vue) const router createRouter({ history: createWebHistory(import.meta.env.BASE_URL), // 使用HTML5 History模式 routes: [ { path: /, name: Home, component: Home, }, { path: /about, name: About, component: About, }, ], }) export default router创建对应的视图组件src/views/Home.vue和src/views/About.vue简单写个template即可。修改src/main.ts使用路由。import { createApp } from vue import App from ./App.vue import router from ./router createApp(App).use(router).mount(#app)修改src/App.vue加入路由视图出口。template div nav router-link to/首页/router-link | router-link to/about关于/router-link /nav router-view / /div /template配置Pinia在src下创建stores/index.ts可选用于统一导出和stores/counter.ts示例store。// src/stores/counter.ts import { defineStore } from pinia import { ref, computed } from vue export const useCounterStore defineStore(counter, () { const count ref(0) const doubleCount computed(() count.value * 2) function increment() { count.value } return { count, doubleCount, increment } })修改src/main.ts使用Pinia。import { createApp } from vue import { createPinia } from pinia import App from ./App.vue import router from ./router const app createApp(App) const pinia createPinia() app.use(pinia).use(router).mount(#app)在组件中使用在任意组件如Home.vue中可以通过const counter useCounterStore()来访问和修改状态。第二个实操心得关于路径别名在配置了别名后有时IDEA的TypeScript服务可能不会立即识别导致导入语句报红虽然运行正常。你可以尝试点击IDEA顶部菜单的File - Invalidate Caches...并重启IDEA或者直接在终端运行pnpm run type-check如果配置了该脚本来触发一次类型检查通常能解决问题。5. 优化构建与开发体验基础功能都有了现在我们来优化一些细节让项目更健壮、开发更顺畅。5.1 环境变量与模式管理Vite使用.env文件来加载环境变量。这些变量会通过import.meta.env暴露给客户端源码。创建环境文件.env: 所有模式下都会加载。.env.development: 仅在开发模式 (npm run dev) 下加载。.env.production: 仅在构建模式 (npm run build) 下加载。定义变量在.env.development中VITE_API_BASE_URLhttp://localhost:3000/api在.env.production中VITE_API_BASE_URLhttps://api.my-domain.com注意只有以VITE_开头的变量才会被Vite暴露给客户端。服务端或构建时的变量应使用其他前缀。在代码中使用const apiBaseUrl import.meta.env.VITE_API_BASE_URL5.2 配置 SVG 图标组件可选但推荐在项目中直接导入SVG文件作为组件使用非常方便。我们需要安装vite-plugin-svg-icons。安装pnpm add -D vite-plugin-svg-icons配置vite.config.tsimport { createSvgIconsPlugin } from vite-plugin-svg-icons import path from path export default defineConfig({ // ... 其他配置 plugins: [ vue(), createSvgIconsPlugin({ iconDirs: [path.resolve(process.cwd(), src/assets/icons)], // 指定图标目录 symbolId: icon-[dir]-[name], // 符号ID格式 }), ], })创建全局组件src/components/SvgIcon.vuetemplate svg aria-hiddentrue :classsvgClass use :xlink:hrefsymbolId / /svg /template script setup langts import { computed } from vue const props defineProps({ name: { type: String, required: true, }, className: { type: String, default: , }, }) const symbolId computed(() #icon-${props.name}) const svgClass computed(() { if (props.className) { return svg-icon ${props.className} } return svg-icon }) /script style scoped .svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } /style在src/main.ts中引入并注册import virtual:svg-icons-register // 引入注册脚本 import SvgIcon from /components/SvgIcon.vue const app createApp(App) app.component(SvgIcon, SvgIcon) // 注册为全局组件 // ... 其他use使用将SVG文件放入src/assets/icons目录假设文件名为user.svg在组件中即可使用template SvgIcon nameuser classNamecustom-class / /template5.3 生产构建分析与优化依赖预构建Vite会自动对node_modules中的依赖进行预构建并将其转换为ESM格式。这个过程在第一次npm run dev时发生。如果你新增了依赖可以手动触发npx vite optimize或pnpm exec vite optimize。分包策略Manual Chunks在vite.config.ts中可以通过build.rollupOptions.output.manualChunks来手动分割代码包将一些不常变动的第三方库单独打包利用浏览器缓存。export default defineConfig({ // ... 其他配置 build: { rollupOptions: { output: { manualChunks: { vue: [vue, vue-router, pinia], // 将Vue生态库打包在一起 ui: [element-plus], // 将UI库打包在一起 }, }, }, }, })使用构建分析插件安装rollup-plugin-visualizer可以可视化分析构建产物的体积。pnpm add -D rollup-plugin-visualizer在vite.config.ts中引入并配置import { visualizer } from rollup-plugin-visualizer export default defineConfig({ plugins: [ // ... 其他插件 visualizer({ open: true, // 构建完成后自动打开分析报告页面 filename: dist/stats.html, // 分析报告输出文件 }), ], })运行pnpm run build后会自动生成一个stats.html文件并在浏览器打开你可以清晰地看到每个模块的大小从而针对性优化。6. 常见问题排查与项目收尾在搭建和后续开发中你可能会遇到一些问题。这里列举几个常见的及其解决方案。6.1 TypeScript 类型报错找不到模块或其声明文件问题在导入.vue文件或某些第三方库时IDEA/TypeScript提示Cannot find module ... or its corresponding type declarations。排查与解决检查安装首先确保你已经安装了该库及其类型声明文件。对于Vue生态类型通常包含在主包中。对于其他库可能需要安装types/包例如pnpm add -D types/lodash。检查.d.ts声明文件对于自定义模块如.vue文件或没有类型声明的库需要在项目根目录或src目录下创建一个类型声明文件例如src/env.d.ts或src/shims-vue.d.ts。// src/shims-vue.d.ts declare module *.vue { import type { DefineComponent } from vue const component: DefineComponent{}, {}, any export default component } // 声明其他自定义模块 declare module *.svg { const content: string export default content }确保这个文件被包含在tsconfig.json的include数组中。重启TypeScript语言服务在IDEA中点击底部状态栏的TypeScript版本号选择“Restart TypeScript Service”。或者使用快捷键CtrlShiftP(Win/Linux) 或CmdShiftP(Mac)输入“Restart TS Server”。6.2 开发服务器运行正常但页面空白或报错问题控制台没有错误但浏览器页面空白或有运行时错误。排查与解决检查浏览器控制台打开浏览器开发者工具查看Console和Network面板。常见的错误有404错误检查index.html中引入的脚本路径是否正确通常是/src/main.ts。检查Vite配置的base选项如果是部署在子路径下。语法错误检查你的Vue/TypeScript代码是否有语法错误。ESLint应该能提前捕获大部分。组件未注册如果使用了全局组件如SvgIcon确保在main.ts中正确注册。检查热更新是否生效尝试修改一个简单的模板内容如App.vue中的文字保存后看页面是否自动刷新。如果没有可能是Vite的HMR出了问题可以尝试重启开发服务器。清除浏览器缓存有时旧的缓存会导致问题尝试使用无痕模式访问或强制刷新CtrlShiftR或CmdShiftR。6.3 生产构建后资源路径错误问题本地开发正常但构建后部署到服务器CSS、JS或图片资源加载失败404。排查与解决检查vite.config.ts中的base选项这个选项决定了所有静态资源的基础路径。如果你的应用部署在域名的根路径如https://www.example.com/则base应为/默认值。如果部署在子路径如https://www.example.com/my-app/则base必须设置为/my-app/。export default defineConfig({ base: process.env.NODE_ENV production ? /my-app/ : /, // 根据环境动态设置 // ... })检查资源引用方式在CSS或JS中引用静态资源如图片时应使用相对路径或别名避免使用绝对路径/除非你明确知道它在生产环境的位置。Vite在构建时会处理这些资源路径。使用import.meta.env.BASE_URL在模板中动态构建路径时可以使用import.meta.env.BASE_URL它会自动替换为配置的base值。6.4 项目收尾与脚本完善最后让我们完善一下package.json中的脚本并添加一些有用的配置。{ scripts: { dev: vite, build: vue-tsc --noEmit vite build, // 先进行类型检查再构建 preview: vite preview, lint: eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix, // 执行ESLint检查并自动修复 type-check: vue-tsc --noEmit, // 仅进行类型检查 prepare: husky install // 如果后续要集成Git Hooks如husky } }现在你的项目已经从一个空文件夹成长为一个结构清晰、功能完备、开发体验优秀的现代化Vue 3应用骨架。它包含了Vue 3 TypeScript Vite 的核心技术栈。ESLint Prettier 的代码规范和格式化。Vue Router 和 Pinia 的路由与状态管理。路径别名、环境变量、SVG图标组件等实用配置。生产构建分析与优化建议。这个项目模板完全可以作为你未来所有Vue 3项目的起点。你可以根据实际需求继续集成UI库如Element Plus、Ant Design Vue、HTTP客户端如axios、测试框架如Vitest等。最重要的是通过这次亲手搭建你对项目中的每一行配置、每一个依赖都有了更深的理解这将在未来的开发和问题排查中给你带来巨大的回报。