通过该文章你可以获取什么?
- 能够实现 命令行交互小项目
- 通过命令行实现一个 cli脚手架项目:
- 包括项目模板的快速创建
- git模板仓库的拉取创建等
- 自定义代码模板,命令快速创建
一、初始化项目
- node init 或者 yarn init 新建一个项目。
- 新建脚本目录,创建脚本入口文件。这边以(
bin/main.js)举例。 - 脚本文件中首行写入:
#!/usr/bin/env node,代表脚本运行在node环境
4. pakeage绑定脚本: 。
- 在项目目录通过
sudo npm link建立项目链接。取消链接使用npm unlink [package.json中的name]
至此,我们实现了通过命令行调用项目中的脚本。
我们可以在
bin/main.js,加入console.log("我的第一个Cli脚本")。然后在通过cmd命令调用my-cli进行验证。
二、引入开发依赖
我们需要的开发依赖主要如下:
- commander : *命令行操作相关。
- shelljs : *调用执行shell。
- inquirer : *交互式问答 cmd 工具。
- git-clone : 可选,用于clone git模板仓库。
- tracer : 可选,更好看的console输出,带颜色。
- fs-extra: 可选,操作文件。
//package.json
{
"name": "your-cli",
"version": "1.0.0",
"main": "index.js",
"author": "maguangcan",
"bin": {
"my-cli": "./bin/main.js"
},
"devDependencies": {
"commander": "^8.3.0",
"git-clone": "^0.2.0",
"shelljs": "^0.8.5",
"tracer": "^1.1.5",
"fs-extra": "^10.0.0",
"inquirer": "^8.2.0"
}
}
三、定义创建命令行
接下来我们开始编写创建模板、克隆模板等相关脚本。 新建创建脚本文件: create-project.js 。名字任取。
main.js 脚本编写
#!/usr/bin/env node
// 第一行命令代表该文件在node环境下运行
const program = require('commander')
const createProject = require('./create-project') //引入外部的我们定义的创建脚本。
// 声明版本信息
program
.version('1.0.0')
.description('我的第一个脚手架~')
//声明命令:my-cli create,关联到 create-project.js
// [project] 代表可选参数,可以自行配置。该demo表示项目名。
program.command('create [project]')
.action((project) => createProject(project))
program.addHelpText('after', `
Example call:
$ create [project] 项目名:非必填
`);
//执行解析
program.parse(process.argv);
设置模板目录
在项目目录中创建目录
templates,目录名在create-project中引用,可自行设置。模板目录下,创建自己的模板项目。 下文以MyTemplate举例。
create-project.js 脚本编写
const clone = require('git-clone') //该库用于通过git创建模板,无需该功能的可以不使用
const shell = require('shelljs');
//每一个日志前加入标识
const log = require('tracer').colorConsole({
format: `CLI=>{{message}}`
})
const fs = require('fs-extra');
const path = require('path');
//问答库
var inquirer = require('inquirer')
log.info('创建例子:my-cli create [my-project]')
//模板列表:这里设置了三个项目模板
const TemplateList = {
MyTemplate: "[ ]我的第一个模板",
Git: "[ ]从GIT获取模板"
}
//获取模板路径
const PWD_PATH = shell.pwd()
const TPL_PATH = path.resolve(__dirname, '../templates')
//拷贝模板到指定目录
async function copyTplDirs(tplName, targetDir) {
const targetPath = targetDir && targetDir !== '.' ? `${PWD_PATH}/${targetDir}` : `${PWD_PATH}`
log.info(`正在生成模板代码,生成位置:${PWD_PATH} ...`)
//创建文件夹
await fs.promises.access(targetPath)
.catch(async err => await fs.promises.mkdir(targetPath, { recursive: true }));
//复制文件
fs.copy(`${TPL_PATH}/${tplName}`, targetPath, {
filter: (src) => {
//TODO 过滤非必要文件夹,处理一些特殊的文件
return !new RegExp('/node_modules|.git/').test(src)
}
}).then(() => {
log.info('**创建完成...**')
})
}
//创建项目
module.exports = async function createProject(project) {
//选择模板问答
const answerTpl = await inquirer.prompt([{
type: 'list',
name: 'template',
message: '选择创建模板:',
choices: [TemplateList.MyTemplate, TemplateList.Git]
}])
switch (answerTpl.template) {
//内置模板
case TemplateList.MyTemplate:
//拷贝文件夹:对应 template/MyTemplate模板目录。
copyTplDirs('MyTemplate', project)
break
//git创建模板
case TemplateList.Git:
//选择模板
inquirer.prompt([{
type: 'input',
name: 'gitUrl',
message: '请输入git模板地址:',
}]).then((answers) => {
// log.info('结果为:' + answers.gitUrl)
if (answers.gitUrl) {
clone(answers.gitUrl, `${PWD_PATH}/${project}`, null, function () {
shell.rm('-rf', `${PWD_PATH}/${project}/.git`)
log.info('项目创建完成!')
})
} else {
log.error('Git地址异常!')
}
})
break
default:
log.warn('**模板开发中...**')
break;
}
}
CMD 在任意目录执行命令验证。
my-cli create my-demo
GIT 例子。
功能进一步设想
- 1、在模板文件中定义配置语法,在创建目录读取一个配置文件,根据相关配置进行不同的构建生成。
- 2、增量更新:对已生成的文件更新,保持现有文件内容,里面新增插入标识。新增时插入到指定标识区间。 ...
See you~~
-3/300-