从 零 搭建 CLI

前言

记得刚毕业那会,新开项目,脚手架都是在老项目上直接拷贝,再删除多余的业务代码,费时费力,且不好维护,扩展性差。稍不留神,还留下多余的东西,后人接手,难以维护治理。这时,就要拿出 CLI,来定制符合自己业务的功能的 CLI

使用到的库

commander 定义命令行指令

inquirer 交互

chalk 美化命令输出

实现简单CLI

1. 初始化项目,生成package.json

bash 复制代码
     pnpm init && pnpm add commander inquirer chalk
json 复制代码
{
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "chalk": "^5.3.0",
    "commander": "^11.0.0",
    "inquirer": "^9.2.11"
  }
}

2. 根目录创建index.mjs

js 复制代码
#! /usr/bin/env node
console.log('我是自定义指令');

#! /usr/bin/env node 作用是告诉电脑用 【node】 执行文件

3. 修改 package.json 注册命令(test)

json 复制代码
{
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "bin": {
    "test": "index.mjs"
  },
  "dependencies": {
    "chalk": "^5.3.0",
    "commander": "^11.0.0",
    "inquirer": "^9.2.11"
  }
}

ps: 项目要使用ESModule,得配置 type 为 【module】

4. 使用 npm link,并输入test,控制台将输出 【我是自定义指令】

bash 复制代码
 npm link  & test

效果如下

commander

上面实现了最简单的CLI命令,如果要实现例如 vue create xxx 的能力,我们就要借用 【commander】

1. 修改 index.mjs

js 复制代码
#! /usr/bin/env node

import fs from 'node:fs';
import path from 'node:path';

import chalk from 'chalk';

import { Command } from "commander";

const program = new Command();

program
    .command('create <文件名字> [文件后缀(默认.js)]') // 指定名字和参数
    .description('创建文件') // 注释 test -h
    .action((filename, filesuffix = 'js') => {
        // create 命令逻辑
        // chalk 美化 console.log 输出文案

        const pathUrl = path.resolve(process.cwd(), `${filename}.${filesuffix}`);
        const content = '// 我是注释' + new Date().getSeconds()
        if (fs.existsSync(pathUrl)) {
            // 文件存在
            console.log(chalk.red('要创建的文件名已存在'))
        } else {
            fs.appendFileSync(pathUrl, content, { encoding: 'utf-8' })
        }
        console.log(chalk.green(filename, filesuffix));
    })

program.parse(process.argv)

2. 使用test create 创建 index.js

将会在当前路径下得到index.js 文件

bash 复制代码
test create index

效果如下

inquirer

上面借用【commander】, 实现了简单的create功能,接下用【inquirer】,实现复杂的命令行交换能力

1. 修改 index.mjs

js 复制代码
#! /usr/bin/env node

import fs from 'node:fs';
import path from 'node:path';

import chalk from 'chalk';

import { Command } from "commander";
import inquirer from 'inquirer';

const program = new Command();

program
    .command('createPKG') // 指定名字和参数
    .description('创建package.json 文件') // 注释 test -h
    .action(() => {
        const pathUrl = path.resolve(process.cwd(), 'package.json');
        if (fs.existsSync(pathUrl)) {
            console.log(chalk.red('package.json文件已存在'))
        } else {
            inquirer
                .prompt([
                    {
                        name: 'name',
                        type: 'input',
                        message: '项目名称'
                    },
                    {
                        name: 'version',
                        type: 'input',
                        message: '版本号',
                        default: '1.0.0' // 默认值
                    },
                    {
                        name: 'description',
                        type: 'input',
                        message: '项目的描述'
                    }
                ]) // 录入问题
                .then((answers) => {
                    console.log(answers);
                    fs.appendFileSync(pathUrl, JSON.stringify(answers), { encoding: 'utf-8' })
                })

        }
    })


program.parse(process.argv)

2. test createPKG 创建 package.json 文件

bash 复制代码
test createPKG

效果如下

总结

日常工作或者学习中,可以通过CLI,集成自己的工具, 减少一些重复的工作,提高效率。

ora 用于loading
fs-extra fs 扩展库

相关推荐
Vicky&James几秒前
WPF到Web的无缝过渡:英雄联盟客户端项目OpenSilver迁移实战
前端·wpf
m0_748233644 分钟前
RabbitMQ 进阶
android·前端·后端
不想有bug的小菜鸟13 分钟前
vue3使用iframe全屏展示pdf效果
前端·pdf
m0_7482386314 分钟前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
u01005596014 分钟前
前端代理,解决跨域问题讲解
前端
quitv19 分钟前
react脚手架配置别名
前端·javascript·react.js
m0_5287238128 分钟前
前端如何进行性能优化
前端·性能优化
化作繁星30 分钟前
在 Vue 3 中,如何缓存和复用动态组件
前端·vue.js·缓存
一粒沙-1 小时前
iOS 将GIF图分享至微信
前端·ios
graywen1 小时前
从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
前端