搭建一个简单的cli工具
2020-06-10 本文已影响0人
Territory_Cheng
目前公司采用的项目结构是基于vue-cli脚手架,再在基础上进行通用组件、业务组件的封装和抽离,目前已经比较完善和稳定。但每次一个新的项目入厂,需要复制拷贝到新的项目目录,比较繁琐,通过搭建一个简单的cli工具,那么几个命令行就解决了。
其实大致的原理为:通过命令行来识别具体的信息,然后直接下载远程git仓库的代码到本地机器。
搭建具体流程
- 创建项目文件夹tcy-cli
-
npm init
初始化package.json - 安装commander、download-git-repo依赖包
- 安装修改控制台输出内容样式的chalk、好看的加载圆圈效果ora
非必选
- 编写相关脚手架命令行识别代码
- 发布到npm
安装包的时候,不要使用
--save-dev
,因为包的依赖信息会放在devDependencies
中,这样在全局安装脚手架的时候,不会安装依赖包,要使用--save
commander可以对命令行做解析的库,可以解析我们在命令行输入,如tcy-cli init <projectName>
inquirer是常规交互式命令行用户接口的集合,提供给 Node.js 一个方便嵌入,漂亮的命令行接口,功能有简化询问终端用户问题,解析,验证答案,提供错误反馈等等
download-git-repo可以下载git仓库的代码
具体代码
#! /usr/bin/env node
const program = require('commander');
const download = require('download-git-repo')
const inquirer = require('inquirer')
const chalk = require('chalk')
const ora = require('ora')
const fs = require('fs')
const spinner = ora(chalk.yellow('Downloading template ...'))
const Version = '1.1.7'
// 修改项目package.json
function setPackage(projectName, answers) {
const packagePath = `${projectName}/package.json`
const packageJson = fs.readFileSync(packagePath, 'utf-8')
const packageResult = JSON.stringify(Object.assign(null, JSON.parse(packageJson), answers), null, 4)
fs.writeFileSync(packagePath, packageResult)
}
// 修改项目名称配置文件
function setProjectName(projectName, fullName, shortName) {
const configPath = `${projectName}/src/conf/index.js`;
const str =
`// 项目全称
const FullName = '${fullName}'
// 项目简称
const ShortName = '${shortName}'
export {
FullName,
ShortName
}
`
fs.writeFileSync(configPath, str)
}
// 设置空业务路由
function setEmptyRouterMap(projectName) {
const routerPath = `${projectName}/src/router/asyncRouterMap.js`
const str =
`// 业务路由表
export const asyncRouterMap = []
`
fs.writeFileSync(routerPath, str)
}
// 名称校验
function validateName(val) {
if(/^[\u4e00-\u9fa5]+$/.test(val)) {
return true
} else {
return "name must be chinaese"
}
}
// 问答内容
const promptList = [
// 项目全称
{
type: 'input',
message: 'please set project fullname',
name: 'fullName',
validate: validateName
},
// 项目简称
{
type: 'input',
message: 'please set project shortname',
name: 'shortName',
validate: validateName
},
// 是否需要初始演示路由
{
type: 'list',
message: 'do you need a example router:',
name: 'router',
default: 'no',
choices: [
"no",
"yes"
]
}
]
program.version(Version, '-v, --version')
.command('init <projectName>')
.action((projectName) => {
inquirer.prompt(
promptList
).then(answers => {
spinner.start()
download('github:tianzhu1992/blocks-admin-vue', projectName, (err) => {
spinner.succeed()
const {fullName, shortName, router} = answers
// 设置package.json的名称与版本号
setPackage(projectName, {name: projectName, version: Version})
// 修改项目名称信息
setProjectName(projectName, fullName, shortName)
// 设置静态初始路由
if(router === 'no') {
setEmptyRouterMap(projectName)
}
// 下载代码成功/失败提示
console.log(err ? chalk.red('Something Wrong In Download Template') : chalk.green('Download Template Success'))
})
});
})
program.parse(process.argv);
-
#! /usr/bin/env node
是执行这个文件时使用node
方式执行 -
program.version
是解析别人输入tcy-cli -v
或tcy-cli --version
时输出的版本号 -
command
指定和解析用户输入的信息,通过<projectName>
来匹配相应的输入信息 -
action
是根据解析的输入信息来获取仓储并在回调执行接下来的任务 -
inquirer.prompt
根据定义的问题来收集用户填写的内容,并在回调的形参answers
中以键值对的形式展现 -
download
的第一个参数下载地址不是填我们git
的网址,按照上述的格式填就行,第二个参数是生成的项目名,第三个参数是错误的回调执行函数,如果没有错误信息,则表示执行成功
发布到npm
首先得需要一个npm账号,如没有,利用邮箱注册下https://www.npmjs.com/
登录账号
npm login
发布到npm
npm publish