开发脚手架工具包
- commander: 命令行插件
const { program } = require('commander')
program.version('1.0.0')
const { program } = require('commander')
program.version('1.0.0')
//创建新项目
program
.command('create <app-name>')
.description('创建一个新项目')
.option('-t, --template <template-name>', '选择一个模板下载')
.action((appName, options) => {
console.log(appName, options.template)
})
program.parse(process.argv)
// 执行命令 node index.js create my-app -t react
// 打印出: my-app react
- figlet :大型字符-终端打印大型文字
const figlet = require('figlet')
figlet('Hello World!!', function (err, data) {
if (err) {
console.log('Something went wrong...')
console.dir(err)
return
}
console.log(data)
})
// 打印出:
_ _ _ _ __ __ _ _ _
| | | | ___| | | ___ \ \ / /__ _ __| | __| | |
| |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| '__| |/ _` | |
| _ | __/ | | (_) | \ V V / (_) | | | | (_| |_|
|_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_(_)
- download-git-repo: 从 git 仓库下载代码
const download = require('download-git-repo')
download('github:vuejs/vue', 'test/tmp', function (err) {
console.log(err ? 'Error' : 'Success')
})
// 打印出: Success
- ora: 终端 loading 插件
const ora = require('ora')
const spinner = ora('Loading unicorns').start()
setTimeout(() => {
spinner.color = 'yellow'
spinner.text = 'Loading rainbows'
}, 1000)
setTimeout(() => {
spinner.stop()
}, 3000)
// 打印出: Loading unicorns
// 1s 后打印出: Loading rainbows
// 3s 后打印出: Loading rainbows
- chalk: 终端打印彩色文字
const chalk = require('chalk')
console.log(chalk.blue('Hello world!'))
// 打印出: Hello world!
- shelljs: 执行 shell 命令
const shell = require('shelljs')
// git 命令是否存在
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git')
shell.exit(1)
}
- inquirer: 命令行交互插件
const inquirer = require('inquirer')
const questions = [
{
type: 'input',
name: 'name',
message: '请输入项目名称',
},
{
type: 'input',
name: 'author',
message: '请输入作者名称',
},
{
type: 'list',
name: 'template',
message: '请选择模板',
choices: ['react', 'vue'],
},
]
inquirer.prompt(questions).then((answers) => {
console.log(answers)
})
// 打印出:
// { name: 'my-app', author: 'col0ring', template: 'react' }
一个简单的脚手架
新建目录
mkdir my-cli && cd my-cli # 初始package.json npm init -y
安装依赖
npm i commander figlet download-git-repo ora chalk shelljs inquirer
package.json
文件如下:{ "name": "xmllein-cli", "version": "1.0.3", "main": "index.js", "author": "lein", "license": "MIT", "bin": { "xmllein": "./bin/index.js" }, "dependencies": { "chalk": "^4.1.2", "commander": "^11.0.0", "download-git-repo": "^3.0.2", "figlet": "^1.6.0", "inquirer": "^8.2.0", "ora": "^5.1.0", "shelljs": "^0.8.5" } }
新建文件 入口文件
mkdir bin && cd bin touch index.js
目录如下:
. ├── README.md ├── bin │ ├── index.js │ └── init.js ├── package.json └── yarn.lock
index.js
文件代码如下:#!/usr/bin/env node const params = require('commander') const { promisify } = require('util') const asyncFiglet = promisify(require('figlet')) const chalk = require('chalk') const inquirer = require('inquirer') const init = require('./init') const figlet = require('figlet') // 打印日志 const log = (content) => { console.log(chalk.green(content)) } // 版本 params.version('1.0.0') // name 参数 params.option('-n, --name <name>', 'output name') params.on('--help', function () { console.log( '\r\n' + figlet.textSync('xmllein-cli', { font: '3D-ASCII', horizontalLayout: 'default', verticalLayout: 'default', width: 120, whitespaceBreak: true, }) ) }) // 打印 logo const printLogo = async () => { let data = await asyncFiglet('xmllein-cli') log(data) } // 创建项目命令 params .command('create <projectName>') .description('创建项目') .action(async (projectName) => { // 打印 logo await printLogo() log('准备创建项目....') // 命令行交互 let answer = await inquirer.prompt([ { name: 'language', type: 'list', message: '请选择开发语言', choices: ['JavaScript', 'TypeScript'], }, ]) if (answer.language === 'JavaScript') { log('创建JavaScript项目') init(projectName) } else { log('创建TypeScript项目') } }) // 解析参数 params.parse(process.argv)
init.js
文件代码如下:#!/usr/bin/env node const { promisify } = require('util') const ora = require('ora') const download = promisify(require('download-git-repo')) const chalk = require('chalk') const shell = require('shelljs') const inquirer = require('inquirer') /** * 封装下载的方法 * @param {string} path * @param {string} name */ function downloadRepositorie(path, name) { return new Promise((resolve, reject) => { const spinner = ora('下载模板中....') spinner.start() download(path, name, { clone: true }, (err) => { if (err) { // 下载完成 spinner.fail('下载失败') reject(err) } // 下载完成 spinner.succeed('下载完成') resolve() }) }) } // 打印日志 const log = (content) => { console.log(chalk.green(content)) } module.exports = async (projectName) => { log(`创建项目:${projectName}`) // 如果目录存在,提示用户是否覆盖 if (shell.test('-d', projectName)) { let answer = await inquirer.prompt([ { name: 'cover', type: 'confirm', message: '目录已存在,是否覆盖?', }, ]) if (answer.cover) { // 删除目录 shell.rm('-rf', projectName) } else { return } } // 下载模板 await downloadRepositorie( 'direct:http://github.com/xmllein/react18.x_mobile_template#main', projectName ) // 安装依赖 log(` 下载完成,请执行下面命令启动任务: ================================= cd ${projectName} yarn install or npm install yarn dev or npm run dev `) }
本地执行命令
node bin/index.js create test
打包发布
# 要通过nrm 切换到 npm 源 npm login npm publish
- 发布成功后,可以通过
npm i xmllein-cli -g
全局安装,然后执行xmllein create test
创建项目
- 发布成功后,可以通过