第一步:初始化一个基于node的项目
- mkdir jeeta
- cd jeeta
- npm init -y
第二步:初始化完成项目后,找到package.json文件并编辑添加bin属性的配置
- {
- "name": "@jeeta/cli",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "bin": {
- "jeeta": "./bin/index.js"
- },
- "keywords": [],
- "author": "",
- "license": "ISC",
- "type": "module",
- "dependencies": {
- "chalk": "^4.1.2",
- "commander": "^9.4.0",
- "inquirer": "^9.1.2",
- "log-symbols": "^5.1.0",
- "ora": "^6.1.2"
- },
- "devDependencies": {
- "@babel/core": "^7.19.1",
- "@babel/eslint-parser": "^7.19.1",
- "eslint": "^8.23.1",
- "eslint-plugin-vue": "^9.5.1"
- }
- }
其中的"jeeta":"./bin/index.js"就是cli命令执行是的入口文件,其中命令为jeeta;
当前在该项目的根目录执行jeeta还是会提示找不到命令的错误提示,稍等后续步骤执行项目的命令后才可。
第三步:编辑./bin/index.js文件
- #!/usr/bin/env node
-
- console.log('hello cli')
'运行
该入口文件只做了打印日志的输出操作,用于验证jeeta的命令执行;jeeta cli的正确使用有两种方法:
1、将该项目打包并发布到npm仓库然后按照到本地,这种适用于cli开发完毕并可发布的场景;
2、使用npm link命令进行本地安装。
我们选择方法2进行
- npm link
- # 如果本地安装了yarn可以使用
- yarn link
- # 本地安装完成后执行以下命令
- > jeeta
- hello cli
以上完成了最基本的cli工具的实现过程。
对应实际的CLI工具开发场景可能需要提供-h或--help帮助、create等,下面就实现一个包含一个jeeta命令帮助信息和jeeta create命令的CLI工具。
在项目中我们添加以下依赖:
包名称 | 说明 |
commander | 提供了用户命令行输入 和 参数解析强大功能 |
chalk | 修改控制台中字符串的样式 |
log-symbols | 各种日志级别的彩色符号 |
npm i chalk@4.1.2 commander log-symbols@5.1.0 -S
依赖安装指定了版本,因最新的版本有比较大的变化,直接使用可能出现错误情况。
第一步:完善./bin/index.js文件脚本
- #!/usr/bin/env node
-
- import {Command} from 'commander'
- import {commands} from '../src/commands/index.js'
- import { readFile } from 'fs/promises';
-
- /**
- * 注册option
- * @param {Object} commander commander实例
- * @param {Object} option 每个命令配置对象
- * @returns commander
- */
- const registerOption = (commander, option) => {
- return option && option.length ? commander.option(...option) : commander
- }
- /**
- * 注册action
- * @param {Object} commander commander实例
- * @param {Object} commandEle 每个命令配置对象
- * @returns commander
- */
- const registerAction = (commander, commandEle) => {
- const { command, description, alias, options, action } = commandEle
- commander
- .command(command) // 命令的名称
- .description(description) // 命令的描述
- .alias(alias)
- // 循环options
- options && options.reduce(registerOption, commander)
- commander.action((options)=>{console.log(options)})
- return commander
- }
-
- const cli = new Command();
- const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url)));
- // 循环创建命令
- cli.version(pkg.version)
-
- commands.reduce((cli,commandEle)=>{
- const { command, description, alias, options, action } = commandEle
- if(command){
- const thisCommand = cli.command(command) .description(description) .alias(alias);
- options && options.reduce(registerOption, thisCommand)
- thisCommand.action(action)
- }else{
- options && options.reduce(registerOption, cli)
- cli.action(action)
- }
-
- return cli
- },cli)
-
- cli.parse(process.argv)
在node
程序中,通过process.argv
可获取到命令的参数,以数组返回;然后通过commander的program进行解析。
第二步:在根目录新建commands文件夹并新建文件index.js
- mkdir src
- cd src
- mkdir commands
- cd commands
编辑commands下的index.js文件内容
- import createCmd from './create.js'
- import helpCmd from './help.js'
-
- export const commands = [
- createCmd,
- helpCmd
- ]
分别新建create.js和help.js
- // create.js
-
- import {successLog} from '../utils/log.js'
- // create command
- const createCmd ={
- command: 'create
' , - description: 'create a new project',
- alias: 'c',
- options: [
- ['-r, --react', 'react template'],
- ['-v, --vue', 'vue template'],
- ['-v2, --vue2', 'vue2 template'],
- ['-v3, --vue3', 'vue3 template']
- ],
- action: createAction,
- examples: ['-r', '--react', '-v', '--vue', '-v2', '--vue2', '-v3', '--vue3'].map((v) => `create projectName ${v}`)
- }
-
- function createAction(projectName, options) {
- console.log(projectName, options)
- };
- export default createCmd
-
- // help.js
- import chalk from 'chalk'
- import {
- commands
- } from './index.js';
- import {infoLog} from '../utils/log.js'
-
- const helpCmd = {
- options: [
- ['-h, --help', 'JEETA Help'],
- ],
- action: helpAction,
- examples: ['-h', '--help', '-V', '--version'].map((v) => `${v}`)
- }
-
- // help
- function helpAction() {
- infoLog(chalk.green('如何使用JEETA-CLI:'))
- commands.forEach((command, index) => {
- // console.log(command)
- console.log(' ', chalk.keyword('orange')(index + 1), `${command.command||'jeeta帮助'}命令`)
- command.examples && command.examples.forEach((example) => {
- console.log(` - jeeta ${example}`)
- })
- });
- };
-
- export default helpCmd
-
-
以上代码段为两个js文件内容,注意拆分。
第三步在根目录新建utils文件夹及log.js
- mkdir utils
- cd utils
完善logs.js文件内容
- import logSymbols from 'log-symbols';
-
- export function successLog(message){
- console.log(logSymbols.success, message);
- }
-
- export function errLog(message){
- console.log(logSymbols.error, '打印错误日志');
- console.log(logSymbols.error, message);
- }
-
- export function infoLog(message){
- console.log(logSymbols.info, message);
- }
-
- export function warningLog(message){
- console.log(logSymbols.warning, message);
- }
完成以上代码,执行jeeta -h命令或jeeta create demo命令查看效果。
查看帮助信息命令
创建项目命令