本文將手把手帶你構建一個支持遠程模板下載、自定義項目名稱,并完成模塊化拆分的 CLI 腳手架工具,適用于初創項目、團隊內部工具或者開源項目快速初始化。
🧩 為什么要自己造一個 CLI 腳手架?
在日常開發中,我們常用腳手架如 create-react-app
、vue-cli
來初始化項目,它們幫我們完成繁瑣的初始化配置。如果你:
- 想統一團隊的項目初始化結構;
- 想搭建自己的模板體系;
- 想通過命令行一鍵拉取模板代碼;
那自定義腳手架就是你的不二選擇!
📦 項目結構設計(模塊化)
我們先設計一套清晰的目錄結構,便于后續拓展和維護:
my-cli/
├── bin/
│ └── my-cli.js # CLI 命令入口
├── lib/
│ ├── init.js # 初始化流程調度
│ ├── download.js # 模板下載邏輯
│ ├── log.js # 統一日志封裝
│ └── repo.js # 倉庫地址統一管理
├── package.json
🛠? 核心依賴庫說明
庫名 | 用途描述 |
---|---|
commander | CLI 命令行參數解析 |
download-git-repo | 支持 GitHub/Gitee 等倉庫模板下載 |
ora | 終端加載動畫 |
chalk | 控制臺美化輸出 |
inquirer (可選) | 增強交互體驗,如模板選擇 |
🧱 一步步構建 CLI 工具
Step 1??:初始化并安裝依賴
mkdir my-cli && cd my-cli
npm init -ynpm install commander download-git-repo ora chalk
Step 2??:編寫命令入口 bin/my-cli.js
#!/usr/bin/env node
const { program } = require('commander');
const init = require('../lib/init');program.version('1.0.0').command('init <projectName>').description('初始化一個項目模板').action((projectName) => {init(projectName);});program.parse(process.argv);
別忘了給該文件執行權限:
chmod +x bin/my-cli.js
并在package.json
添加:
"bin": {"my-cli": "./bin/my-cli.js"
}
Step 3??:編寫模板下載邏輯 lib/download.js
const download = require('download-git-repo');
const ora = require('ora');
const { error, success } = require('./log');function downloadTemplate(repo, dest) {const spinner = ora('📦 正在下載模板...').start();return new Promise((resolve, reject) => {download(repo, dest, { clone: false }, (err) => {if (err) {spinner.fail('? 下載失敗');error(err);reject(err);} else {spinner.succeed('? 下載成功');resolve();}});});
}module.exports = downloadTemplate;
Step 4??:統一日志輸出 lib/log.js
const chalk = require('chalk');exports.success = (msg) => console.log(chalk.green(msg));
exports.error = (msg) => console.log(chalk.red(msg));
exports.info = (msg) => console.log(chalk.blue(msg));
Step 5??:管理模板倉庫地址 lib/repo.js
module.exports = {vue: 'github:yourname/vue-template',react: 'github:yourname/react-template',default: 'github:yourname/base-template'
};
你可以拓展為支持
inquirer
交互選擇模板。
Step 6??:主流程調度 lib/init.js
const path = require('path');
const fs = require('fs');
const downloadTemplate = require('./download');
const repo = require('./repo');
const { error, success } = require('./log');async function init(projectName) {const targetDir = path.resolve(process.cwd(), projectName);if (fs.existsSync(targetDir)) {error(`目錄 ${projectName} 已存在`);process.exit(1);}const templateRepo = repo.default;try {await downloadTemplate(templateRepo, targetDir);success(`🎉 項目 ${projectName} 初始化完成`);console.log(`👉 你可以執行:\n cd ${projectName}\n npm install\n npm start`);} catch (err) {error('初始化失敗');}
}module.exports = init;
🚀 如何運行和測試
npm link # 將 CLI 注冊為全局命令
my-cli init my-app
你的模板就會從遠程倉庫拉取并生成到 my-app
目錄!
🌱 后續拓展方向
目標 | 技術點 |
---|---|
多模板選擇 | 使用 inquirer 提供列表選擇 |
模板渲染變量 | 加入 ejs 渲染 package.json 等文件 |
模板配置項 | 提供 .myclirc 管理默認倉庫 |
支持 GitLab / Gitee | 使用 clone: true 下載私有倉庫 |