PingAn-cli 脚手架开发
1,初始化package.json文件
npm init -y
2, 创建一个index.js文件,文件头添加
#!/usr/bin/env node
解释: 调用系统环境变量中的node解释器执行文件
还有一个中写法: #!/usr/bin/node
console.log('PingAn-cli 脚手架工具')
3, package.json文件中添加abc命令
"bin": {
"PingAn-cli": "index.js"
}
添加一个PingAn-cli 命令, 执行当前目录下面的index.js文件
4, 项目目录下执行: npm link 链接到全局
npm link: 用来在本地项目和本地npm模块之间建立连接,可以在本地进行模块测试
或者: npm link PingAn-cli
解除: npm unlink PingAn-cli
5, 输入 PingAn-cli
输出:PingAn-cli 脚手架工具
6, 教授级命令行工具参数设计
PingAn -h --help 查看使用帮助
PingAn -V --version
PingAn list 列出所有模版
PingAn init <template-name> <project-name> 基于指定的模版进行项目初始化
7, 获取用户的输入命令
(1) // 获取用户输入的, 从输入的第三个开始
// 原生获取名利行参数
console.log(process.argv)
(2)通过 commander 获取命令行参数
npm install commander
const program = require('commander');
program
.version('0.1.0')
.option('-C, --chdir <path>', 'change the working directory')
.option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
.option('-T, --no-tests', 'ignore test hook');
8, 根据不同的命令创建不同的模版
定义多个不同的模版
const templates = {
'pa-vue': {
url: 'https://github.paic.com.cn/xxx/vue-template',
downloadUrl: 'https://github.com.cn:xxx/vue-template#master',
description: 'vue模版'
},
'pa-react': {
url: 'https://github.paic.com.cn/xxx/react-template',
downloadUrl: 'https://github.com.cn:xxx/react-template#master',
description: 'react模版'
},
'pa-angular': {
url: 'https://github.paic.com.cn/xxx/angular-template',
downloadUrl: 'https://github.com.cn:xxx/angular-template#master',
description: 'angurl模版'
}
}
9, 下载模版,需要安装download-git-repo
npm install download-git-repo
download(url, name, { clone: true }, (err) => {
if (err) {
console.log(err)
return
} else {
console.log('success')
}
10, 安装向导插件,实现交互式场景
npm install inquirer
const inquirer = require('inquirer')
inquirer.prompt([{
type: 'input',
name: 'author',
message: '请输入作者名称'
}]).then((answers) => {
console.log(answers.author)
})
10, 安装模版引擎
npm install handlebars
const handlebars = require('handlebars')
handlebars.compile(packageContent)(answers)
11, 创建动态package.json文件
package.json
{
"name": "{{ name }},
"version": "1.0.0",
"description": "{{ description}}",
"scripts": {
"test": "echo \"Error: no test specified\"
},
"keywords": [],
"author": "{{ author }}",
"license": "ISC",
"bin": {
"PingAn": "index.js"
},
"dependencies": {
"commander": "^4.0.1",
"download-git-repo": "^3.0.2",
}
}
package.json动态模版文件
12, 视觉美化
npm install ora
const ora = rquire('ora')
// 开始下载
const spinner = ora('正在下载模版......')
spinner.start()
// 下载失败
spinner.fail()
// 现在成功
spinner.succeed()
13, chalk 文字添加chalk样式,增强视觉效果
npm install chalk
const chalk = require('chalk');
console.log(chalk.blue('Hello world!'));
14, 如果下载的过程中想添加日志符合
npm install log-symbols
console.log(logSymbols.success,chalk.yellow('初始化模版成功'))
15, NPM 发包
npm install --global PingAn-cli
1, npm login
2, npm publish
index.js 文件
代码复制可以直接运行
#!/usr/bin/env node
// console.log('PingAn-cli 脚手架工具')
// 获取用户输入的, 从输入的第三个开始
// 原生获取名利行参数
// console.log(process.argv)
// const commander = require('commander')
const program = require('commander');
const download = require('download-git-repo')
const inquirer = require('inquirer')
const fs = require('fs')
const handlebars = require('handlebars')
const ora = require('ora')
const chalk = require('chalk')
const logSymbols = require('log-symbols')
const templates = {
'pa-vue': {
url: 'https://github.paic.com.cn/xxx/vue-template',
downloadUrl: 'https://github.com.cn:xxx/vue-template#master',
description: 'vue模版'
},
'pa-react': {
url: 'https://github.paic.com.cn/xxx/react-template',
downloadUrl: 'https://github.com.cn:xxx/react-template#master',
description: 'react模版'
},
'pa-angular': {
url: 'https://github.paic.com.cn/xxx/angular-template',
downloadUrl: 'https://github.com.cn:xxx/angular-template#master',
description: 'angurl模版'
}
}
program
.version('0.1.0')
.option('-C, --chdir <path>', 'change the working directory')
.option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
.option('-T, --no-tests', 'ignore test hook');
// PingAn init a a-name 基于a模版进行初始化,初始化项目叫做:a-name
program
.command('init <template> <project>')
.description('初始化项目模版')
.action(function(templateName, projectName){
// 下载之前loading
const spinner = ora('正在下载模版......').start()
// 根据模版名称下载对应的模版到本地并起名为projectName
// console.log(templateName, projectName);
// console.log(templates[templateName])
// 第一个参数: 仓库地址
// 第二个参数: 下载路径,默认当前路径下的项目名称下
const { downloadUrl } = templates[templateName]
download(downloadUrl, projectName, { clone: true }, (err) => {
if (err) {
spinner.fail()
console.log(logSymbols.error,chalk.red(err))
return
}
spinner.succeed() // 下载成功
// 把项目下的package.json文件读取出来
// 使用向导的方式采集用户输入的值
// 使用模版引擎把用户输入的数据解析到package.json文件中
// 解析完毕后,把解析之后的结果重新写入package.
inquirer.prompt([{
type: 'input',
name: 'name',
message: '请输入项目名称'
}, {
type: 'input',
name: 'description',
message: '请输入项目简介'
}, {
type: 'input',
name: 'author',
message: '请输入作者名称'
}]).then((answers) => {
console.log(answers)
// 把采集到的用户输入数据解析替换到package.josn文件中
const packagePath = `${projectName}/package.json`
const packageContent = fs.readFileSync(packagePath, 'utf8')
const packageResult = handlebars.compile(packageContent)(answers)
console.log(packageResult)
fs.writeFileSync(packagePath, packageResult)
console.log(logSymbols.success,chalk.yellow('初始化模版成功'))
})
})
});
program
.command('list')
.description('查看所有可用模版')
.action(() => {
for (let key in templates) {
console.log(`
${key} ${templates[key].description}
`)
}
})
program
.command('exec <cmd>')
.alias('ex')
.description('execute the given remote cmd')
.option("-e, --exec_mode <mode>", "Which exec mode to use")
.action(function(cmd, options){
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
}).on('--help', function() {
console.log('');
console.log('Examples:');
console.log('');
console.log(' $ deploy exec sequential');
console.log(' $ deploy exec async');
});
program
.command('*')
.action(function(env){
console.log('deploying "%s"', env);
});
program.parse(process.argv);