打造专属 React 脚手架:从 0 到 1 开发 CLI 工具
前言:
在前端开发中,重复搭建项目环境是个低效的事儿。要是团队技术栈固定(比如 React + AntD + Zustand + TS ),每次从零开始配路由、状态管理、UI 组件,既耗时又容易出错。这时候,自定义 CLI 脚手架 就派上大用场了 —— 一行命令就能生成标准化项目,直接进入业务开发!
本文就带你从 0 到 1 开发一套 React 脚手架 CLI,实现 “拉取模板 + 初始化 Git + 自动装依赖” 全流程,让项目搭建像 “搭积木” 一样简单 ✨
一、需求拆解:脚手架要解决什么问题?
我们的目标是做一个 “开箱即用” 的 React 脚手架,核心功能:
- 模板一键拉取:从 GitHub 仓库拉取包含 React 路由、AntD 组件、Zustand 状态管理的项目模板。
- 自动初始化流程:无需手动
git init
、npm install
,工具自动完成。 - 开发命令指引:安装完直接提示启动命令,无缝衔接开发。
二、技术选型:哪些工具能帮我们实现?
commander
:解析命令行参数(定义create <projectName>
命令)。download-git-repo
:从 Git 仓库下载模板(支持 GitHub、GitLab 等)。child_process
:Node.js 内置模块,执行终端命令(如git init
、npm install
)。
三、代码实现:一步步打造 CLI 工具
1. 初始化项目 & 安装依赖
# 新建脚手架项目目录
mkdir react-scaffold-cli
cd react-scaffold-cli# 初始化 package.json
npm init -y# 安装核心依赖
npm install commander download-git-repo
2. 编写 CLI 核心逻辑(cli.js
)
#!/usr/bin/env node
const { program } = require("commander");
const download = require("download-git-repo");
const path = require("path");
const { execSync } = require("child_process");// 定义命令:react-scaffold create <projectName>
program.command("create <projectName>").description("创建 React + AntD + Zustand + TS 项目").action((projectName) => {// 1. 配置模板仓库 & 目标路径const repo = "github:jackywq/react-antd-zustand-scaffold#main"; const targetPath = path.join(process.cwd(), projectName); // 2. 从 Git 拉取模板download(repo, targetPath, {}, (err) => {if (err) {console.error("❌ 模板下载失败:", err);return;}console.log("✅ 模板下载完成!");try {// 3. 初始化 Git 仓库(解决 husky 依赖 .git 问题)console.log("📦 初始化 Git 仓库...");execSync(`cd ${projectName} && git init`, { stdio: "inherit" });// 4. 自动安装依赖console.log("📦 开始安装依赖...");execSync(`cd ${projectName} && npm install`, { stdio: "inherit" });// 5. 提示启动命令console.log("✅ 依赖安装完成!");console.log(`✅ 项目创建成功,可执行:cd ${projectName} && npm run start`);} catch (installErr) {console.error("❌ 依赖安装失败:", installErr);}});});// 解析命令行参数,触发对应逻辑
program.parse(process.argv);
3. 代码逐行解析
(1)基础配置:让脚本可执行
#!/usr/bin/env node
这行是 Shebang 声明,告诉系统 “用 Node.js 运行这个脚本”,这样我们就能直接用 react-scaffold create ...
调用,无需手动输入 node cli.js
。
(2)依赖引入:工具的 “左臂右膀”
const { program } = require("commander"); // 解析命令行参数
const download = require("download-git-repo"); // 拉取 Git 模板
const path = require("path"); // 处理文件路径
const { execSync } = require("child_process"); // 执行终端命令
commander
:让我们能定义create
命令,解析用户输入的projectName
。download-git-repo
:从 GitHub 仓库下载模板代码(一行代码实现git clone
功能)。child_process
:执行git init
、npm install
等终端命令,自动化初始化流程。
(3)命令定义:告诉用户怎么用
program.command("create <projectName>").description("创建 React + AntD + Zustand + TS 项目").action((projectName) => { ... });
command("create <projectName>")
:定义create
命令,<projectName>
是用户要创建的项目名称(必填)。description(...)
:添加命令描述,执行react-scaffold --help
时会显示。action(...)
:命令的 “执行逻辑”,用户输入create my-app
时,就会触发这里的代码。
(4)核心流程:项目创建全自动化
// 模板仓库地址(替换成你自己的 GitHub 仓库!)
const repo = "github:jackywq/react-antd-zustand-scaffold#main";
// 目标路径:当前目录 + 项目名(如 ./my-app)
const targetPath = path.join(process.cwd(), projectName);
repo
:格式是github:用户名/仓库名#分支
,指定从哪拉取模板。targetPath
:计算项目要创建的路径(比如用户当前在~/projects
,执行create my-app
就会生成~/projects/my-app
)。
download(repo, targetPath, {}, (err) => { ... });
调用 download-git-repo
拉取模板,失败会提示 模板下载失败
,成功则继续执行初始化流程。
execSync(`cd ${projectName} && git init`, { stdio: "inherit" });
execSync(`cd ${projectName} && npm install`, { stdio: "inherit" });
git init
:初始化 Git 仓库(解决husky
等工具依赖.git
目录的问题)。npm install
:自动安装项目依赖(基于模板里的package.json
)。{ stdio: "inherit" }
:让终端实时输出命令执行日志(用户能看到git init
、npm install
的过程)。
四、测试 & 发布:让脚手架真正能用起来!
1. 本地测试:直接运行 CLI
# 在脚手架项目目录执行
node cli.js create my-app
- 观察终端输出:
- 成功:
模板下载完成!
→初始化 Git 仓库...
→依赖安装完成!
- 失败:检查网络(能否访问 GitHub)、模板仓库地址是否正确。
- 成功:
2. 发布到 npm:让所有人都能安装
(1)修改 package.json
,添加关键配置
{"name": "react-scaffold-cli","version": "1.0.0","bin": {"react-scaffold": "cli.js" // 定义全局命令},"dependencies": {"commander": "^11.0.0","download-git-repo": "^3.0.2"}
}
bin
:定义全局命令react-scaffold
,用户安装后可直接用react-scaffold create ...
调用。dependencies
:声明生产依赖(commander
、download-git-repo
必须被安装)。
(2)发布到 npm 仓库
# 1. 登录 npm(确保已注册账号)
npm login# 2. 发布脚手架
npm publish
发布成功后,任何人都能通过 npm install -g react-scaffold-cli
全局安装你的脚手架!
五、优化 & 扩展:让脚手架更强大
1. 模板仓库替换:用自己的项目模板
把 repo
换成你自己的 GitHub 仓库地址,比如:
const repo = "github:your-username/your-react-template#main";
模板仓库里可以包含:
- React 路由配置(
react-router-dom
) - AntD 基础组件(
Button
、Layout
等) - Zustand 状态管理示例(用户登录状态、全局配置)
2. 增加交互:让用户选模板
如果想支持 多模板选择(比如 “React + Vue + ...”),可以用 inquirer
实现交互:
npm install inquirer
const inquirer = require("inquirer");program.command("create <projectName>").action(async (projectName) => {// 让用户选择模板const { template } = await inquirer.prompt([{type: "list",name: "template",message: "选择项目模板",choices: ["react-antd", "vue-element", "next-js"]}]);// 根据选择拼接不同的 repo 地址const repoMap = {"react-antd": "github:your-username/react-template#main","vue-element": "github:your-username/vue-template#main"};const repo = repoMap[template];// 后续流程和之前一样...});
3. 错误处理:让用户更清楚哪里出错了
如果下载模板失败,可以细化错误提示:
download(repo, targetPath, {}, (err) => {if (err) {if (err.message.includes("not found")) {console.error("❌ 模板仓库不存在,请检查地址!");} else if (err.message.includes("network")) {console.error("❌ 网络错误,请检查网络连接!");} else {console.error("❌ 模板下载失败:", err);}return;}// ...后续流程
});
六、总结:脚手架的价值不止于 “偷懒”
通过本文的 CLI 开发,你不仅学会了 “拉取模板 + 自动化流程” 的核心逻辑,更重要的是理解了 “标准化开发” 的意义:
- 团队新人无需了解复杂技术栈配置,一行命令就能开始开发;
- 项目结构、依赖版本统一,减少 “环境不一致” 导致的 Bug;
- 后续迭代模板时,所有项目都能同步更新,真正做到 “一处修改,处处生效”。
如果你想让脚手架更强大,还能扩展:
- 支持 多模板选择(React / Vue / 小程序);
- 集成 代码规范检测(ESLint、Prettier);
- 对接团队内部 Git 仓库,实现更定制化的流程。
现在,赶紧用你开发的脚手架生成一个项目,体验 “一键启动” 的快感吧~ 🚀
我的npmjs和github地址:
npmjs: react-scaffold-starter-cli - npm
github: https://github.com/jackywq/react-scaffold-starter-cli
github:https://github.com/jackywq/react-antd-zustand-scaffold
(如果觉得本文有用,欢迎点赞Csdn Github、分享给需要的同学,也可以在评论区交流你遇到的问题和优化思路~)