概念

什么是脚手架?

脚手架是一个定制化的工具,用于快速生成项目的基础结构和代码文件,以及提供一些常用的命令和功能。通过编写自己的脚手架,你可以定义项目的目录结构、文件模板,管理项目的依赖项,生成代码片段,以及提供命令行接口等功能

我们常见的脚手架例如 vue-cli Angular CLI Create React App

这些脚手架的一些局部功能,可以通过 nodejs 来实现

流程

  1. 初始化一个 nodejs 项目
  2. 配置 package.json 文件,添加一个 bin 配置项,指定可执行文件的路径
  3. 新建一个 bin 目录,并在其中新建一个 index.js 文件
  4. 安装第三方库 commander inquirer ora download-git-repo
  5. 编写 js 代码,实现脚手架的功能
  6. 运行 npm link 或者 npm install -g 全局安装脚手架
  7. 使用 vue-cli 创建项目

实现

下面我们来尝试着实现一个简单的脚手架,可以通过简单的命令,来快速构建一个 vue 项目

首先使用 npm init 初始化一个 nodejs 项目

1
npm init -y

然后配置 package.json 文件,添加一个 bin 配置项,指定可执行文件的路径

1
2
3
4
"type": "module", //使用import导入模块的话需要设置这个
"bin": {
"test-cli": "src/index.js"
},

接着新建一个 bin 目录,并在其中新建一个 index.js 文件

然后介绍要用到的第三方库,具体的使用可以在 npm 官网直接搜对应的包名就可以找到使用方法

  • commander

Commander 是一个用于构建命令行工具的 npm 库。它提供了一种简单而直观的方式来创建命令行接口,并处理命令行参数和选项。使用 Commander,你可以轻松定义命令、子命令、选项和帮助信息。它还可以处理命令行的交互,使用户能够与你的命令行工具进行交互

  • inquirer

Inquirer 是一个强大的命令行交互工具,用于与用户进行交互和收集信息。它提供了各种丰富的交互式提示(如输入框、选择列表、确认框等),可以帮助你构建灵活的命令行界面。通过 Inquirer,你可以向用户提出问题,获取用户的输入,并根据用户的回答采取相应的操作。

  • ora

Ora 是一个用于在命令行界面显示加载动画的 npm 库。它可以帮助你在执行耗时的任务时提供一个友好的加载状态提示。Ora 提供了一系列自定义的加载动画,如旋转器、进度条等,你可以根据需要选择合适的加载动画效果,并在任务执行期间显示对应的加载状态。

  • download-git-repo

Download-git-repo 是一个用于下载 Git 仓库的 npm 库。它提供了一个简单的接口,可以方便地从远程 Git 仓库中下载项目代码。你可以指定要下载的仓库和目标目录,并可选择指定分支或标签。Download-git-repo 支持从各种 Git 托管平台(如 GitHub、GitLab、Bitbucket 等)下载代码。

然后我们开始编写 js 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/env node
import { program } from "commander";
import inquirer from "inquirer";
import fs from "node:fs";
import { checkPath, downloadTemp } from "./utils.js";
let json = fs.readFileSync("./package.json", "utf-8");
json = JSON.parse(json);

program.version(json.version); //创建版本号
//添加create 命令 和 别名crt 以及描述 以及 执行完成之后的动作
program
.command("create <project>")
.alias("ctr")
.description("create a new project")
.action((project) => {
//命令行交互工具
inquirer
.prompt([
{
type: "input",
name: "projectName",
message: "project name",
default: project,
},
{
type: "confirm",
name: "isTs",
message: "是否支持typeScript",
},
])
.then((answers) => {
if (checkPath(answers.projectName)) {
console.log("文件已存在");
return;
}

if (answers.isTs) {
downloadTemp("ts", answers.projectName);
} else {
downloadTemp("js", answers.projectName);
}
});
});

program.parse(process.argv);

#!/usr/bin/env node 是一个 特殊的注释 用于告诉操作系统用 node 解释器去执行这个文件,而不是显式地调用 node 命令

在 bin 目录下再编写一个 utils.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import fs from "node:fs";
import download from "download-git-repo";
import ora from "ora";
const spinner = ora("下载中...");
//验证路径
export const checkPath = (path) => {
return fs.existsSync(path);
};

//下载
export const downloadTemp = (branch, project) => {
spinner.start();
return new Promise((resolve, reject) => {
download(
`direct:https://gitee.com/chinafaker/vue-template.git#${branch}`,
project,
{ clone: true },
function (err) {
if (err) {
reject(err);
console.log(err);
}
resolve();
spinner.succeed("下载完成");
}
);
});
};

接着生成软连接挂载到全局,便可以全局执行 test-cli 这个命令

你也可以发布到 npm 上让别人下载使用

1
2
3
# npm login   # 登录npm
# npm publish # 发布包,别人就可以下载了
npm link # 将当前项目链接到全局

配置完成之后 就可以使用命令进行测试了

1
test-cli

输出类似信息

1
2
3
4
5
6
7
8
9
10
11
Usage: test-cli [options] [command]

当前版本

Options:
-V, --version output the version number
-h, --help display help for command

Commands:
create|c <projectName> 创建项目
help [command] display help for command

当你不需要使用这个脚手架的时候,可以执行 npm unlink 取消链接

1
npm unlink test-cli