创建Node脚手架工具(上)

1,278 阅读4分钟

简介

前端有各种各样的脚手架工具, 比如我们常用的vue-cli, create-react-app等工具. 为我们前端早期工程的开发, 带来极大的便利.

这么便利的node cli, 是不是特别想知道是如何开发的? 接下来, 为大家介绍一下怎样开发一个脚手架工具.

课程计划

本系列, 将分为三节: 上中下

  • (上):主要介绍开发Node工具, 需要常用的工具库.
  • (中):手把手开发一个Node工具, 实现的功能是: 类似create-react-app, 通过这个工具, 可以创建基本的react编程结构.
  • (下): 如何发布自己的私包到npmjs上.

现在开始第一节内容的介绍.

常见的一个cli工具, 一般会实现什么功能呢? 看看我们属性的命令: 我们以npm init, npm install为例:

  • init是一条命令. 用来创建一个package.json文件.
  • init命令执行后, 要你输入一些配置比如: "package name:", "author"等信息.
  • 最后还有一个确认的信息: "Is this OK(yes)"
  • 另外我也可以加一些参数, 比如npm init -y, 这样创建过程就使用默认配置.
  • 使用npm install来安装包时, 也可以看到进度条和简单的loading动画
  • 最后能看到控制台里部分信息是高亮显示, 比如红色, 绿色, 加粗等.

现在我们一一介绍, 要实现这些功能. 我们可用的武器有哪些?

常见的工具库

  • commander
  • inquirer
  • ora
  • chalk
  • which

commander

是一个工具包,其作用是让node命令行程序的制作更加简单,封装后的node命令行接口, 简单易用.

安装:

npm install commander -D

输入-v或--version时, 显示cli的版本好.

const program = require('commander');

// 处理-v, --version时的输出.
program.version(require('../package.json').version, '-v, --version');

// 解析输入参数. 记得放在最后即可.
program.parse(process.argv); 

创建一条命令

  • 命令为: create
  • 描述为: Create a new project.
  • 支持一个参数name, 表示项目名称.
const program = require('commander');
program
  .version(require('../package.json').version, '-v, --version')
  .command('create <name>')
  .description('Create a new project')
  .action(name => {
    console.log(name);
  })

  program.parse(process.argv); 

当执行create命令后, 没有提供参数时, 会提示缺少参数name. 提供后, 控制台就输出我们提供的name值.

到现在为止, create命令就算新建了. 实际的命令处理逻辑, 写在action的回调里即可. 另外, commander的用法很多. 具体的可以参考github上commander的介绍.

inquirer

使用它很容易的完成用户和命令行的交互. 比如npm init时, 要我们输入package name, author等等信息. 最后还要我们输入yes确认等交互.

具体的用法,基于上面的代码. 我们添加和命令行的交互. 输入一个author信息和最后确认.

#!/usr/bin/env node

const program = require('commander');
const inquirer = require('inquirer');

program
  .version(require('../package.json').version, '-v, --version')
  .command('create <name>')
  .description('Create a new project')
  .action(name => {
    inquirer.prompt([
      // 输入类型
      {
        type: 'input',
        name: 'author',
        message: 'Please input the author name.'
      },
      // 确认类型.
      {
        type: 'confirm',
        name: 'continune',
        message: 'Is that ok?'
      }
    ]).then(result => {
      // 输出: {author, continune}的实际的值.    
      console.log(result);
    })
  })

  program.parse(process.argv); 

ora

输出进度条, loading等信息

const p = ora('创建中...')
p.start();
setTimeout(() => {
  p.stop();
}, 3000);

控制台中, |一直在转, 3s后停止.

chalk

用来在控制台中输出不同样式的信息. 比如文字颜色, 文字背景等.

const chalk = require('chalk')
console.log(chalk.red('some error'))

which

通过PATH环境变量到该路径内查找可执行文件,所以基本的功能是寻找可执行. 比如查找是否安装了npm。

const which = require('which');
const chalk = require('chalk');

// 查找系统中用于安装依赖包的命令
function findNpm() {
  const npms = ['tnpm', 'cnpm', 'npm'];
  for (let i = 0; i < npms.length; i++) {
    try {
      // 查找环境变量下指定的可执行文件的第一个实例
      which.sync(npms[i]);
      return npms[i]
    } catch (e) {
    }
  }
  throw new Error(chalk.red('请安装npm'));
}

一份完整的代码:

bin/cli文件

#!/usr/bin/env node

const program = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');
const ora = require('ora');

program
  .version(require('../package.json').version, '-v, --version')
  .command('create <name>')
  .description('Create a new project')
  .action(name => {
    console.log(name);

    inquirer.prompt([
      {
        type: 'input',
        name: 'author',
        message: 'Please input the author name.'
      },
      {
        type: 'confirm',
        name: 'continune',
        message: 'Is that ok?'
      }
    ]).then(result => {
      console.log(result);
      console.log(chalk.red('some error'))

      const p = ora('创建中...')
      p.start();
      setTimeout(() => {
        p.stop();
      }, 3000);
    })
  })

  program.parse(process.argv); 

package.json文件

{
  "name": "cli-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "xcli": "./bin/cli"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chalk": "^2.4.2",
    "commander": "^3.0.1",
    "download-git-repo": "^2.0.0",
    "inquirer": "^7.0.0",
    "ora": "^3.4.0",
    "which": "^1.3.1"
  }
}

项目代码

代码

把命令行安装到node_module下

// 进入项目文件夹
npm link

安装成功后. xcli工具就可以在任意地方使用了.

xcli create xxx

有了这些武器, 我们开发一个node命令就非常的容易了. 这些工具的完整用法. 可以直接在github上查看官方使用说明即可.

接下来, 我们要使用这些工具, 开发一个实际的工具. 实现的功能是: 类似create-react-app, 通过这个工具, 可以创建基本的react编程结构。

详情请查看: 创建Node脚手架工具(中)