loading
搭建一个脚手架就是为了搭建项目的基本结构和提供项目规范与约定,一个复杂的工作做多了,慢慢的也会变得麻木,搭建一个脚手架,便能通过简单的初始化命令,快速的完成这些重复的工作,脚手架可以说是一种常用工具,也是团队提高效率的手段
'axios'
'chalk'
'commander'
'download-git-repo'
'figlet'
'fs-extra'
'inquirer'
'ora'
mkdir ben-cli
cd ben-cli
mkdir bin
npm init
cd bin
touch cli.js # 创建启动文件
-----------------
ben-cli
├─ bin
│ └─ cli.js # 启动文件
├─ lib
│ └─ create.js
│ └─ creator.js
│ └─ request.js
│ └─ util.js
├─ README.md
└─ package.json
-----------------
package.json 文件,将制定文件入口设为 cli.js
{
"name": "ben-cli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"bin": {
"ben": "./bin/cli", // ben 别名
},
"scripts": {
"test": "echo \"prError: no test specified\" && exit 1"
},
"files": [
"bin",
"lib"
],
"keywords": [
"ben-cli",
"脚手架"
],
"author": {
"name": "jsben",
"email": "455531691@qq.com"
},
"license": "MIT",
"dependencies": {
"axios": "^0.24.0",
"chalk": "^4.1.1",
"commander": "^8.3.0",
"download-git-repo": "^3.0.2",
"fs-extra": "^10.0.0",
"inquirer": "^8.2.0",
"ora": "^5.4.0"
}
}
方便开发调试,使用 npm link 链接到全局
npm link
现在 cmd 命令行输入 ben 就可以执行 cli.js 文件了
npm install commander --save
#! /usr/bin/env node
const program = require('commander')
const chalk = require('chalk')
// 创建指令
program
.command('create <app-name>')
.description('create a new project')
.option('-f, --force', 'overwrite target directory if it exist')
.action((name, options) => {
require('../lib/create')(name,options) // 在 create.js 中执行创建任务
})
program
.command('config [value]')
.description('inspect and modify the config')
.option('-g, --get <path>', 'get value from option')
.option('-s, --set <path> <value>')
.option('-d, --delete <path>', 'delete option from config')
.action((value, options) => {
console.log(value, options)
})
program
.on('--help', () => {
console.log(`\r\nRun ${chalk.cyan(`ben-cli <command> --help`)} for detailed usage of given command\r\n`)
})
program
.version(`ben-cli@${require('../package.json').version}`)
.usage(`<command> [option]`)
program.parse(process.argv);
以上是 commanderAPI,更多有关 commander 的教程可以看看https://zhuanlan.zhihu.com/p/450880320
询问用户是否需要覆盖目录已存在文件
用户选择模板
用户选择版本
获取下载模板的链接
npm install inquirer --save
const path = require("path");
const fs = require("fs-extra");
const inquirer = require("inquirer");
const Creator = require("./Creator");
module.exports = async function (name, options) {
const cwd = process.cwd();
const targetDir = path.join(cwd, name);
if (fs.existsSync(targetDir)) {
if (options.force) {
await fs.remove(targetDir);
} else {
let { action } = await inquirer.prompt([
{
name: "action",
type: "list",
message: "Target directory already exists Pick an action:",
choices: [
{
name: "Overwrite",
value: "overwrite",
},
{
name: "Cancel",
value: false,
},
],
},
]);
if (!action) {
return;
} else if (action === "overwrite") {
// 移除已存在的目录
console.log(`\r\nRemoving...`);
await fs.remove(targetDir);
}
}
}
const creator = new Creator(name, targetDir);
creator.create();
};
我们可以通过 http 请求获取一些仓库管理库提供的 API 获取模板信息
npm install axios --save
const axios = require("axios");
axios.interceptors.response.use((res) => res.data);
async function fetchRepoList() {
return axios.get("https://gitee.com/api/v5/orgs/ben-cli/repos");
}
async function fetchTagList(repo) {
return axios.get(`https://gitee.com/api/v5/repos/ben-cli/${repo}/tags`);
}
module.exports = {
fetchRepoList,
fetchTagList,
};
创建 Generator 类 处理项目生成逻辑
const Inquirer = require("inquirer");
const { fetchRepoList, fetchTagList } = require("./request");
const { wrapLoading } = require("./util");
const downloadGitRepo = require("download-git-repo");
const util = require("util");
const path = require("path");
class Creator {
constructor(name, targetDir) {
this.name = name;
this.target = targetDir;
this.downloadGitRepo = util.promisify(downloadGitRepo);
}
async fetchRepo() {
let repos = await wrapLoading(fetchRepoList, "waiting fetch template");
if (!repos) return;
repos = repos.map((item) => item.name);
const { repo } = await Inquirer.prompt({
name: "repo",
type: "list",
choices: repos,
message: "Please choose a template to create project",
});
return repo;
}
async fetchTag(repo) {
let tags = await wrapLoading(fetchTagList, "waiting fetch tag", repo);
if (!tags) return;
tags = tags.map((item) => item.name);
const { tag } = await Inquirer.prompt({
name: "tag",
type: "list",
choices: tags,
message: "Please choose a tag to create project",
});
return tag;
}
async download(repo, tag) {
const requestUrl = `ben-cli/${repo}${tag ? "#" + tag : ""}`;
await wrapLoading(
this.downloadGitRepo,
"waiting download template",
requestUrl,
path.resolve(process.cwd(), this.target)
);
}
async create() {
const repo = await this.fetchRepo();
const tag = await this.fetchTag(repo);
await this.download(repo, tag);
console.log(`\r\nSuccessfully created project ${chalk.cyan(this.name)}`);
console.log(`\r\n cd ${chalk.cyan(this.name)}`);
console.log(" npm run dev\r\n");
}
}
module.exports = Creator;
这个有啥用的
可以提高团队开发效率
写得不错