1. 项目概述为什么需要自定义Vue3项目脚手架每次启动一个新项目你是不是也厌倦了在命令行里敲下npm create vuelatest然后在一堆选项里反复勾选最后还得手动调整一堆配置作为一个有多年全栈开发经验的工程师我越来越觉得一个趁手的、符合团队或个人习惯的项目脚手架是提升开发幸福感和效率的第一步。Vue3的官方脚手架create-vue固然优秀但它提供的是一个“通用”的起点。对于特定的技术栈偏好比如我习惯用Pinia做状态管理用Element Plus做UI用Vite打包、特定的目录结构规范甚至是预设的代码风格和提交规范每次从零配置都是一次重复劳动。这就是我们今天要聊的在 IntelliJ IDEA 这个强大的IDE里打造一个属于你自己的、一键生成的Vue3项目模板。这不仅仅是创建一个项目而是创建一个“项目工厂”。想象一下新项目初始化不再是繁琐的配置而是一个命令或一次点击一个包含了你所有最佳实践、工具链和基础代码的工程就立即可用。我们将深入IDEA的“文件模板”和“项目模板”功能结合一些脚本技巧实现这个目标。整个过程不依赖任何第三方复杂工具纯粹利用IDEA自身能力和一些Node.js脚本稳定、可控且高度定制化。2. 核心思路与方案选型IDEA模板 vs 自定义CLI要实现自定义项目创建市面上有几种主流方案我们需要根据易用性、定制深度和与IDEA的集成度来做出选择。2.1 主流方案对比方案优点缺点适用场景官方create-vue 手动配置官方维护生态兼容性最好选项灵活。每次重复操作无法固化复杂配置依赖网络。探索性项目、一次性项目。基于degit/plop的代码仓库模板直接克隆Git仓库快速可版本化管理模板。需要额外学习工具与IDE集成弱处理动态变量如项目名较麻烦。团队间共享固定模板。编写自定义CLI工具如create-my-vue功能最强大可交互式问答高度自动化。开发维护成本高需要发布到npm团队成员需全局安装。大型团队、企业级标准化。利用IDEA内置的“项目模板”功能与开发环境无缝集成无需离开IDE配置可视化利用IDEA强大的变量系统。定制能力有一定上限但足够模板文件需放在特定目录。个人或小团队快速启动追求开发流程丝滑。2.2 为什么选择IDEA项目模板经过权衡我选择了IDEA的项目模板方案。原因很直接它完美契合了“在IDEA中创建”这个场景实现了从想法到可运行代码的“最短路径”。零学习成本团队成员不需要记住任何新的CLI命令只需要在熟悉的IDEA“新建项目”界面里选择你的模板。环境集成创建的项目直接就在IDEA里打开所有IDE级别的配置如运行配置、代码风格设置可以一并预设。动态变量支持IDEA模板引擎支持强大的变量替换如${PROJECT_NAME},${USER}在创建时自动填充到文件、配置甚至package.json中。组合性强可以同时创建文件模板如一个标准的Vue组件文件和项目模板形成一套完整的工具链。我们的目标就是将一个配置完善的Vue3项目包括Vite、Router、Pinia、ESLint、Prettier、Element Plus等打包成一个IDEA能识别的模板。接下来我们分步拆解如何实现。3. 打造黄金标准准备你的“样板间”项目在制作模板之前你必须先有一个完美的“样板间”项目。这个项目应该代表了你对Vue3项目的最佳实践。这里我分享我自己的基础配置你可以在此基础上增减。3.1 初始化与基础依赖首先我们还是用官方工具创建一个基础但这次我们记录下所有选择。# 在终端中执行生成一个基础项目 npm create vuelatest my-vue3-template在交互式命令行中我通常会选择TypeScript: YesJSX: NoRouter: Yes (用 history 模式)Pinia: YesESLint: Yes (带eslint-plugin-vue和typescript-eslint)Prettier: YesVitest: 可选根据需求E2E Testing: 通常先不选保持模板简洁项目生成后进入目录安装我必用的UI库和工具库cd my-vue3-template npm install element-plus element-plus/icons-vue npm install axios npm install -D sass3.2 关键配置文件的定制化这是模板的精华所在需要仔细打磨。1.vite.config.ts的优化import { fileURLToPath, URL } from node:url import { defineConfig } from vite import vue from vitejs/plugin-vue import vueJsx from vitejs/plugin-vue-jsx import AutoImport from unplugin-auto-import/vite import Components from unplugin-vue-components/vite import { ElementPlusResolver } from unplugin-vue-components/resolvers // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), vueJsx(), // 即使项目不用JSX也保留避免未来需要时重新配置 // 自动导入 API 如 ref, reactive, onMounted 等无需手动import AutoImport({ imports: [vue, vue-router, pinia], dts: src/auto-imports.d.ts, resolvers: [ElementPlusResolver()], }), // 自动导入组件如 Element Plus 的 ElButton Components({ resolvers: [ElementPlusResolver()], dts: src/components.d.ts, }), ], resolve: { alias: { : fileURLToPath(new URL(./src, import.meta.url)) } }, server: { host: 0.0.0.0, // 允许局域网访问方便移动端调试 port: 5173, open: true, // 自动打开浏览器 proxy: { // 开发环境代理配置示例 /api: { target: http://your-api-server.com, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }, css: { preprocessorOptions: { scss: { additionalData: use /styles/element/index.scss as *; // 全局导入Element Plus样式变量如果需要定制主题 } } } })注意unplugin-auto-import和unplugin-vue-components是神器能极大减少手动 import 的繁琐。但初次使用需要生成类型声明文件dts选项模板中需包含这些生成后的空文件或确保创建流程能自动生成。2.tsconfig.json与eslint的协同确保tsconfig.json中的compilerOptions.paths与 Vite 的alias对应。{ compilerOptions: { baseUrl: ., paths: { /*: [src/*] } } }在.eslintrc.cjs中配置规则以适应团队习惯我通常会关闭一些过于严格的规则并确保其能处理.vue和.ts文件。3. 预设目录结构与示例文件一个清晰的目录结构是项目的骨架。我的src目录通常如下src/ ├── api/ # 所有接口请求封装按模块划分文件 ├── assets/ # 静态资源 ├── components/ # 公共组件 │ ├── common/ # 全局通用组件 (如Loading, ConfirmDialog) │ └── layout/ # 布局组件 (Header, Sidebar) ├── composables/ # Vue3组合式函数 ├── router/ # 路由配置 ├── stores/ # Pinia store按模块划分 ├── styles/ # 全局样式、变量、mixins ├── types/ # TypeScript 类型定义 ├── utils/ # 工具函数 ├── views/ # 页面级组件 ├── App.vue ├── auto-imports.d.ts # AutoImport插件生成 ├── components.d.ts # Components插件生成 └── main.ts在模板中你需要在关键位置放置一些示例文件这比空目录更有指导意义。例如在stores下放一个counter.ts示例在composables下放一个useMouse.ts示例。4. 预设的index.html与全局样式在index.html中预设好移动端适配的meta标签和标题变量。!DOCTYPE html html langzh-CN head meta charsetUTF-8 / link relicon typeimage/svgxml href/vite.svg / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title% VITE_APP_TITLE %/title /head body div idapp/div script typemodule src/src/main.ts/script /body /html在src/styles下创建_variables.scss定义CSS变量创建index.scss作为全局样式入口重置一些默认样式。3.3 封装项目级别的脚本与配置1. 统一的package.json脚本{ scripts: { dev: vite, build: vue-tsc vite build, preview: vite preview, lint: eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix, lint:style: stylelint \src/**/*.{vue,scss,css}\ --fix, prepare: husky install, // 配合Git钩子 type-check: vue-tsc --noEmit } }2. 集成 Git 钩子Husky lint-staged这是保证代码质量的关键一步。安装husky和lint-staged。npm install -D husky lint-staged npx husky install npm pkg set scripts.preparehusky install npx husky add .husky/pre-commit npx lint-staged在package.json中配置lint-staged{ lint-staged: { *.{js,jsx,ts,tsx,vue}: [eslint --fix], *.{vue,scss,css}: [stylelint --fix] } }这样每次提交前会自动对暂存区的文件进行代码格式化。至此你的“样板间”项目已经是一个功能齐全、开箱即用的优秀Vue3项目了。接下来我们要把它“固化”成IDEA模板。4. 将项目转化为IDEA项目模板IDEA的项目模板文件存放在一个特定目录。我们需要将“样板间”项目进行处理并放入该目录。4.1 定位IDEA模板目录IDEA的模板目录通常位于其配置路径下macOS / Linux:~/Library/Application Support/JetBrains/IDE_VERSION/projectTemplatesWindows:C:\Users\YourName\AppData\Roaming\JetBrains\IDE_VERSION\projectTemplatesIDE_VERSION例如IntelliJIdea2023.3。如果目录不存在可以手动创建。4.2 创建模板描述文件在projectTemplates目录下为你模板创建一个新文件夹例如MyVue3Template。在这个文件夹里你需要一个关键的描述文件template.xml。?xml version1.0 encodingUTF-8? template !-- 模板在IDEA新建项目对话框中显示的名称 -- nameMy Custom Vue 3 TS Pinia Element Plus/name !-- 模板描述 -- descriptionA pre-configured Vue 3 project with TypeScript, Router, Pinia, ESLint, Prettier, Element Plus, AutoImport and more./description !-- 模板图标可选 -- iconMyVueIcon.png/icon !-- 分类 -- categoryVue.js/category !-- 变量定义这些变量会在创建项目时由用户输入或自动填充 -- variables !-- PROJECT_NAME 是IDEA内置变量会自动用用户输入的项目名替换 -- variable namePROJECT_NAME expression defaultValue alwaysStoptrue/ !-- 你可以定义自定义变量比如应用标题 -- variable nameAPP_TITLE expression defaultValueMy Vue App alwaysStopfalse/ !-- 包名用于package.json -- variable namePACKAGE_NAME expressiongroovyScript(\return _1.replaceAll([^\\\\w\\\\d-], _).toLowerCase()\, projectName()) defaultValue${PROJECT_NAME} alwaysStopfalse/ /variables !-- 要复制的根目录内容这里指向我们准备好的“样板间”项目 -- root name. sourcepath/to/your/my-vue3-template / /template重要提示source路径可以是绝对路径也可以是相对于此template.xml文件的相对路径。为了便于移植建议将“样板间”项目的完整副本放在MyVue3Template目录下的一个子文件夹如project里然后使用相对路径sourceproject。4.3 处理模板中的动态变量这是模板的灵魂。我们需要在“样板间”项目的文件中用IDEA的变量语法${变量名}替换掉那些需要动态变化的内容。package.json:{ name: ${PACKAGE_NAME}, version: 1.0.0, description: Project ${PROJECT_NAME}, ... }index.html:title${APP_TITLE}/titlevite.config.ts中的proxy目标或其他环境相关配置也可以设为变量。任何包含项目名称的字符串比如README.md的标题。操作技巧你可以先备份一份原始的“样板间”项目然后在副本上进行全局搜索和替换。IDEA也提供了强大的“在路径中替换”功能CtrlShiftR/CmdShiftR。4.4 添加可选的后期生成脚本有时仅仅复制文件还不够。例如我们希望在项目创建后自动运行npm install。IDEA模板支持通过postpone指令和postgen脚本来实现。在template.xml的/template标签前添加!-- 指定哪些操作可以推迟到项目打开后执行 -- postponetrue/postpone然后在模板目录MyVue3Template下创建一个postgen文件夹在里面创建一个可执行脚本。对于 macOS/Linux (postgen/run.sh):#!/bin/bash # 进入新创建的项目目录 cd $1 echo Installing dependencies with npm... npm install if [ $? -eq 0 ]; then echo Dependencies installed successfully. else echo npm install failed. Please check your network or node version. fi对于 Windows (postgen/run.bat):echo off cd /d %1 echo Installing dependencies with npm... call npm install if %errorlevel% equ 0 ( echo Dependencies installed successfully. ) else ( echo npm install failed. Please check your network or node version. )记得给.sh文件添加执行权限 (chmod x run.sh)。IDEA在项目创建后会执行这个脚本并传入新项目的路径作为第一个参数。5. 在IDEA中使用自定义模板完成上述步骤后重启你的IntelliJ IDEA。点击File-New-Project...。在左侧的类别列表中你应该能看到一个新的分类名称就是你之前在template.xml里设置的category例如 “Vue.js”。点击它。在右侧你会看到你的模板“My Custom Vue 3 TS Pinia Element Plus”。选中它。点击“Next”你会看到变量输入界面。PROJECT_NAME需要你输入APP_TITLE和PACKAGE_NAME会有默认值你可以修改。选择项目保存的位置点击“Create”。IDEA会开始复制模板文件并用你输入的值替换所有${变量}。如果配置了postgen脚本它会接着运行安装命令。稍等片刻一个完全按照你心意配置的、依赖也已安装好的Vue3项目就会在IDEA中打开并且已经是一个初始化的Git仓库如果模板包含.gitignore。6. 进阶技巧与问题排查6.1 模板的维护与更新你的技术栈会变最佳实践也会演进。更新模板的推荐流程是用当前模板创建一个临时项目。在该项目中更新依赖、修改配置、优化代码直到它达到新的“黄金标准”。将整个项目目录除了node_modules和.git复制回模板的source目录例如MyVue3Template/project。重新处理动态变量替换。重启IDEA测试新模板。6.2 常见问题与解决方案问题1模板在新建项目对话框中不显示。检查template.xml文件格式是否正确是否放在了正确的projectTemplates子目录下。检查IDEA版本是否匹配目录名。可以尝试清空IDEA缓存 (File-Invalidate Caches...) 并重启。问题2变量替换没有生效。检查在源文件如package.json中变量语法是否正确必须是${VARIABLE_NAME}。检查template.xml中是否正确定义了同名变量。问题3postgen脚本没有执行。检查template.xml中是否设置了postponetrue/postpone。检查postgen脚本是否放在了正确的文件夹且具有可执行权限Linux/macOS。查看日志IDEA的日志文件Help - Show Log in Finder/Explorer中可能有脚本执行失败的详细信息。问题4创建的项目依赖安装失败或脚本报错。策略在postgen脚本中加入更详细的日志或者先注释掉npm install手动在终端里运行以确定是网络问题、权限问题还是脚本路径问题。6.3 分享你的模板如果你想和团队成员共享这个模板最简单的方法就是将整个MyVue3Template文件夹打包让他们解压到自己IDEA的projectTemplates目录下。更优雅的方式是将其放入团队共享的Git仓库并编写一个简单的安装脚本。我个人在实践中发现花半天时间搭建这样一个模板能为未来数十个甚至上百个项目节省大量重复劳动的时间。它不仅统一了团队的技术栈和代码风格更重要的是它将最佳实践“固化”下来新成员上手第一个项目时接触到的就是一个配置完善、结构清晰的工程这对团队的技术传承至关重要。