[学习笔记]从0到1开发自己的cli脚手架工具-乞丐版

109 阅读4分钟

[学习笔记]从0到1开发自己的cli脚手架工具-乞丐版

写一个最基本的 cli 工具,可以下载生成项目模板

起步

首先在文件夹内进行 npm init操作,创建package.json文件,同时,在项目文件夹内创建程序入口文件index.js.

使用 Node 开发命令行工具 所执行的 javascript 脚本必需在顶部加入 #!/usr/bin/env node

index.js顶部内添加#!/usr/bin/env node

接着 写入第一条语句console.log('kvue-cli 脚手架工具')

到此,我们可以进行启动前的最后一步,配置其可以被命令行启动。在package.json中添加

"bin": {
    "kvuecli": "index.js"
}

接着,以管理员身份打开CMD至当前目录(非管理员无权限,无法进行下一步)执行npm link建立软连接,使kvuecli命令可以被识别。(若需要删除当前软连接,只需在当前目录下执行npm unlink)

万事俱备,在cmd窗口内执行kvuecli可以看到控制台输出kvue-cli 脚手架工具

到此,在本地程序就能够正常跑起来了,接下来只需要完善其功能就ok了

命令行参数设计

一个脚手架工具,有自己的命令工具,这里仿造 vuecli的部分命令列表

kvuecli --help 查看使用帮助
kvuecli -V | --version 查看工具的版本号
kvuecli list   查看可用的模板列表
kvuecli init <template-name> 基于指定的模板进行项目初始化

获取控制台输入的命令

脚手架工具通过控制台输入的不同命令执行不同的操作,那么首先我们需要获取到控制台输入的命令参数。

  • 方法一:通过process.argv来获取命令参数

    index.js中添加一条console.log(process.argv),接着在控制台执行kvuecli

    image-20220324095733024

    在不输入其他命令参数时,可以看到控制台输出如上,那么执行kvuecli init kvuecli list呢?

    没错,我们会看到如下结果

    image-20220324100108677

    如此便可获取到命令参数了

  • 方法二:使用commander

    执行npm install commander安装包。

    commander中文文档

    引入const program = require('commander')

    // 配置命令
    program
        .version('0.1.0') // -V 或 --version
    
    program
        .command('init <template> <project>')
        .description('初始化项目模板')
        .action((templateName, projectName) => {
    
            console.log(templateName, projectName)
    
        });
    
    program
        .command('list')
        .description('查看可用项目模板列表')
        .action(() => {
    
            console.log('这里将展示项目模板列表')
    
        });
    
    program.parse(process.argv);
    

    这里先简单配置了两个命令

    • kvuecli init
      • 必需传入template模板名称和project项目名称
    • kvuecli list
      • 展示目前可用模板列表
    • kvuecli --help
      • 包自动生成的,列出当前配置过的命令

准备模板文件

在执行kvuecli init之前,我们需要先准备好一些模板文件以供创建项目,这里用Gitee做演示.

Gitee仓库中创建好一个开源项目

image-20220324104947025

index.js中配置模板信息

image-20220324113028824

完善kvuecli list命令,展示所有模板信息

image-20220324105951121

ok,有了模板信息,有了模板地址,那么在执行kvuecli init的时候只需要下载对应模板就行了

下载模板

这里使用download-git-repo处理模板下载。

执行npm install download-git-repo,并引入const download = require("download-git-repo")

修改kvuecli init逻辑

program
    .command('init <template> <project>')
    .description('初始化项目模板')
    .action((templateName, projectName) => {

        // console.log(templateName, projectName)

        // 取出下载地址
        const { downloadUrl } = templates[templateName]
       
        download('direct:' + downloadUrl, projectName, { clone: true }, (err) => {

            if (err) {
                console.log('下载失败', err);
            } else {
                console.log('下载成功');
            }

        })

    });

再执行kvuecli init tp-test testdl 时,便可以看到成功下载了模板

添加交互

在创建项目时,一般都会有设置项目名,描述,作者等过程,通常是一问一答的形式进行,这个过程也就是交互的过程。这里使用handlebarsinquirer来处理

npm install handlebars

const handlebars = require('handlebars')

npm install inquirer

const inquirer = require('inquirer')

首先在模板仓库中编辑package.json文件,将需要交互动态设置的内容使用{{}}包裹起来

{
  "name": "{{name}}",
  "version": "1.0.0",
  "description": "{{description}}",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "{{author}}",
  "license": "ISC",
  "bin": {
    "kvuecli": "index.js"
  },
  "dependencies": {
    "commander": "^9.1.0",
    "download-git-repo": "^3.0.2"
  }
}

做好以上准备后,接下来有四个步骤来实现这个文件处理过程

  • 模板文件下载好后读取package.json文件
  • 以问答的方式获取到用户输入的值
  • 使用handlebars将用户输入的值解析到package.json
  • 将解析完的package.json文件存储

配置下载模板完成后的引导信息

 download('direct:' + downloadUrl, projectName, { clone: true }, (err) => {

            if (err) {
                console.log('下载失败', err);
            } else {
                console.log('下载成功');

                inquirer.prompt([{
                    type: 'input',
                    name: 'name',
                    message: '请输入项目名称'
                }, {
                    type: 'input',
                    name: 'description',
                    message: '请输入项目介绍'
                }, {
                    type: 'input',
                    name: 'author',
                    message: '请输入作者名称'
                }]).then(answers => {
                    console.log(answers);
                })
            }

        })

在收集完用户填写的信息后进行文件改写,这里使用fs模块

.....then(answers => {
  console.log(answers);
  const packageContent = fs.readFileSync(`${projectName}/package.json`, 'utf-8')
  const packageResult = handlebars.compile(packageContent)(answers)

  // 重写
  fs.writeFileSync(`${projectName}/package.json`,packageResult)

   console.log('初始化模板成功');

})

执行初始化模板,成功解析

image-20220324145044980

美化

  • 使用ora美化下载过程

    注意:ora 最新版只能使用 import 来导入,所以要设置当前项目的默认包管理为 ESModule

    package.json中添加"type": "module"

  • 使用 chalklogSymbols 增加文本样式

以上美化过程不做演示了,文档很详细。