自研脚手架的核心价值在于支持可配置、可扩展的“一类项目”生成,而非 create-react-app 或 vite create 的固定模板;它通过 inquirer、fs-extra、execa 等工具串联用户输入、模板与目标路径,结合占位符渲染、路径安全处理及内联依赖配置,确保生成项目开箱即用。

为什么不用 create-react-app 或 vite create?
因为你要的不是“一个项目”,而是“一类项目”的生成能力。create-react-app 生成的是固定结构的 React 项目,vite create 只能选预设模板(如 vanilla、react、vue),无法按需组合 TypeScript + Tailwind + ESLint 配置 + 自定义目录结构。自研脚手架的核心价值,在于把团队约定的 projectConfig.js、template/ 目录、copy.js 脚本串起来,让 npm run scaffold -- --type=dashboard --lang=ts 这样的命令真正可配置、可扩展、可维护。
怎么用 Node.js 实现最小可行脚手架?
关键不在“造轮子”,而在复用现有生态。你需要三样东西:
-
inquirer:处理交互式提问(比如“项目名?”“是否启用 TypeScript?”),避免硬编码参数 -
fs-extra:替代原生fs,支持递归复制、路径安全判断,copySync('./template/react-ts', targetDir)一行搞定 -
execa:执行 shell 命令,比如在生成后自动运行npm install或git init
别写自己的模板引擎——直接用 lodash.template 或 mustache 处理 {{projectName}} 这类占位符。重点是把用户输入、模板路径、目标路径这三者串通,而不是重写文件系统逻辑。
template/ 目录里该放什么?
不是“把旧项目扔进去就完事”。容易踩的坑是模板里混着真实业务代码、绝对路径、本地 node_modules 引用。正确做法是:
立即学习“前端免费学习笔记(深入)”;
- 所有
package.json中的name、version、description字段必须含占位符,如"name": "{{projectName}}", - 删除
node_modules、dist、.git等非模板内容;保留.gitignore但确保它不含项目特有路径 - 若模板含 TypeScript,
tsconfig.json中的compilerOptions.baseUrl应设为"./",而非硬编码"src",否则跨项目复用时路径解析失败 - 在
template/根目录放一个meta.json,声明该模板支持的参数(如{"lang": ["js", "ts"], "css": ["vanilla", "tailwind"]}),供 CLI 动态校验和提示
如何避免生成后立即报错?
生成完跑不起来,90% 出在路径和依赖上。常见错误现象包括:Cannot find module 'react'、Failed to resolve import './App.tsx'、ESLint: Cannot find module 'eslint-config-airbnb'。
解决思路很实际:
- 生成前先
npm install模板依赖(在 template 目录下执行),再删掉node_modules—— 这样能验证package.json里的devDependencies是否完整且版本兼容 - 所有 import 路径用相对路径(
import { foo } from '../utils'),禁用未配置的路径别名(如@/components),除非你在模板里同步配好vite.config.ts或jsconfig.json - ESLint/Prettier 配置必须内联在模板中,不要靠
extends引用全局或团队私有 npm 包——生成机很可能没装那些包,或版本不匹配
最常被忽略的一点:生成后的 package.json 里 scripts 的值,要和你实际测试过的开发流程一致。比如你模板里写了 "dev": "vite",就得确认 vite 是 devDependencies,而不是 dependencies;否则 npm install 后 npm run dev 会直接报 command not found。



















