1 创建工程
1.1 创建文件并安装依赖
- 创建一个my-cli文件夹
- 执行npm init初始化工程
- 安装依赖
- 创建入口文件, index.js
依赖名称 | 依赖版本 | 依赖作用 |
---|---|---|
chalk | 4.1.2 | log美化工具 |
cli-table | 0.3.11 | 控制台table美化工具 |
commander | 11.1.0 | 命令行工具 |
download-git-repo | 3.0.2 | 拉取远程模板 |
ejs | 3.1.10 | 模板引擎 |
inquirer | 8.2.0 | 交互式选项 |
1.2 配置命令
打开package.json文件
{
"name": "my-cli", // npm包名称
"version": "1.0.0", // npm包版本
"description": "我的脚手架", // 描述
"bin": {
"mc": "index.js" // mc是脚手架命令,index.js是入口文件
}
}
1.3 编辑入口文件
#!/usr/bin/env node
const pkg = require('./package.json');
const program = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');
const downloadGit = require('download-git-repo');
const fs = require('fs');
const path = require("path")
// 定义命令选项
program
.version(pkg.version)
.option("-v, --version", pkg.version)
program
.command("create") // 命令
.description("创建模板") // 命令描述
.action(() => { // 命令行为
// 创建交互式命令行
inquirer.prompt([
{
type: "list", // 交互类型,list是选项
name: "type", // 变量名
message: "请选择模板类型", // 交互提示信息
choices: [
{name: "模板1",value: "temp-one"},
{name: "模板2",value: "temp-two"}
],
validate(val){ // 对用户的输入进行校验
if (val === "temp-one") return true; // 校验通过进行下一步
else return "模板2还在建设当中,敬请期待..." // 校验不通过,并返回提示信息
}
},
{
type: "input", // 交互类型输入
name: "name",
message: "请输入项目名称", // 交互提示信息
default: "my-app", // 当用户不输入时,提供的默认值
}
]).then(values => {
const { type, name } = values;
let api = null;
// 根据用户选择的模板类型,确定模板仓库地址
if (type === "temp-one") {
api = `direct:${git地址1}#${分支名}`
}
if (type === "") {
api = `direct:${git地址2}#${分支名}`
}
const outputDir = path.join(process.cwd(), name);
// 检测当前目录下,是否存在要创建的同名文件夹
fs.access(outputDir, fs.constants.F_OK, function(err){
if (!err){
console.log(`${chalk.red(`创建失败: 当前目录下已经存在${name}目录`)}`)
return
}
// 下载远程模板代码
downloadGit(api, outputDir, { clone: true }, function(err){
if (err) {
console.error(err)
console.log(`${chalk.red(`远程代码加载失败`)}`)
return
}
// 走到这里,说明远程代码已经加载完成。可能需要对模板代码进行一定的编辑
// 所以,这里可以使用ejs进行模板代码的处理。也可以更改某些文件
// 用更改package.json举例子
const pkgJsonPath = `${outputDir}/package.json`;
// 读取模板中package.json文件的内容
fs.readFile(pkgJsonPath, "utf-8", function(err,data){
// 读取失败报错
if (err){
console.error(err)
return;
}
// 合并package.json的内容
const pkgJsonStr = JSON.parse(data);
pkgJsonStr['name'] = name;
const writeJsonStr = JSON.stringfy(pkgJsonStr, null, 2);
fs.writeFile(pkgJsonPath, writeJsonStr, function(err){
// 文件写入失败
if (err) {
console.error(err)
return;
}
// 到这里就全部完成了
})
})
})
})
})
})
1.4 说明
本文章尽量用最简单的方式来说明,脚手架如何开发。大家可以根据需求对代码自行更改;其中对于依赖的使用,可以查找对应依赖的文档进行查看。一般使用通义千问就够了,比较方便
大家可能也会有以下问题
1、git拉取模板时,如何开放模板的clone权限。
用gitlab举例子,去gitlab中选择个人令牌,选择权限范围后,创建个人令牌
然后使用的git地址就变成这样
http://oauth2:${token}@git.your-git-repo.com/template.git
可以看到,@的后半部分是git模板的地址,前半部分是个人令牌
使用download-git-repo库拉取远程代码的时候
要拼成
direct:http://oauth2:${token}@git.your-git-repo.com/template.git#分支名
2、ejs的使用
这个可以根据ejs文档来参考,在download远程模板结束之后,遍历download下来的模板文件,并用ejs引擎进行解析替换即可