从 0 构建自己的脚手架/CLI

571 阅读5分钟

脚手架是我们经常使用的工具,也是团队提效的重要手段,所以系统性的掌握脚手架相关知识,对前端开发者来说是非常重要的.

一、脚手架的简单雏形 🐣

脚手架就是在启动的时候询问一些简单的问题,并且通过用户回答的结果去渲染对应的模板文件,基本工作流程如下:

  1. 通过命令行交互询问用户问题
  2. 根据用户回答的结果生成文件 例如我们在使用  vue-cli 创建一个 vue 项目时的时候 👇

step1:运行创建命令

vue create hello-world

step2:询问用户问题

9ebe1cdcdc004beaa74058b42e14136a_tplv-k3u1fbpfcp-watermark.jpg step3: 最后生成一个带完整约束的项目文件

二、热门脚手架工具库 🔧

实际生产中搭建一个脚手架或者阅读其他脚手架源码的时候需要了解下面这些工具库 👇

名称简介
 commander命令行自定义指令
inquirer命令行询问用户问题,记录回答结果
 chalk控制台输出内容样式美化
 ora控制台 loading 样式
 figlet控制台打印 logo
easy-table控制台输出表格
 download-git-repo下载远程模版(github)
fs-extra系统fs模块的扩展,提供了更多便利的 API,并继承了fs模块的 API
cross-spawn支持跨平台调用系统上的命令

重点介绍下面这些,其他工具可以查看说明文档

1. commander 自定义命令行指令

更多用法 👉 中文文档

简单案例 👇

1.1 新建一个简单的 Node Cli 项目

// package.json
{
  "name": "my-vue",
  "version": "1.0.0",
  "description": "",
  "bin": "./bin/cli.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "T-Roc",
  "license": "ISC",
  "devDependencies": {
    "commander": "^7.2.0"
  }
}

目录结构:

npms-demo             
├─ bin                
│  └─ cli.js          
├─ package-lock.json  
└─ package.json              

1.3 引入 commander 编写代码

# 安装依赖
npm install commander # yarn add commander 
复制代码

完善 bin.js 代码

#! /usr/bin/env node

const program = require('commander')

program
.version('0.1.0')
.command('create <name>')
.description('create a new project')
.action(name => { 
    // 打印命令行输入的值
    console.log("project name is " + name)
})

program.parse()
复制代码

1.3 npm link 链接到全局

  • 执行 npm link 将应用 my-vue 链接到全局
  • 完成之后,在命令行中执行 my-vue

看一下,命令行中的输出内容 👇

~/Desktop/cli/npms-demo ->my-vue

Usage: my-vue [options] [command]

Options:
  -V, --version   output the version number
  -h, --help      display help for command

Commands:
  create <name>   create a new project
  help [command]  display help for command
复制代码

这个时候就有了 my-vue 命令使用的说明信息,在 Commands 下面出现了我们刚刚创建的 create 命令 create <name>,我们在命令行中运行一下

~/Desktop/cli/npms-demo ->my-vue create my-app
project name is my-app
复制代码

这个时候控制台就打印出来 create 命令后面的 <name>my-app 👏

2. chalk 命令行美化工具

chalk(粉笔)可以美化我们在命令行中输出内容的样式,例如对重点信息添加颜色

2.1 安装依赖

npm install chalk # yarn add chalk
复制代码

2.2 基本使用

在 npms-demo 项目中打开 bin/cli.js

#! /usr/bin/env node

const program = require('commander')
const chalk = require('chalk')

program
.version('0.1.0')
.command('create <name>')
.description('create a new project')
.action(name => { 
    // 打印命令行输入的值

    // 文本样式
    console.log("project name is " + chalk.bold(name))

    // 颜色
    console.log("project name is " + chalk.cyan(name))
    console.log("project name is " + chalk.green(name))

    // 背景色
    console.log("project name is " + chalk.bgRed(name))

    // 使用RGB颜色输出
    console.log("project name is " + chalk.rgb(4, 156, 219).underline(name));
    console.log("project name is " + chalk.hex('#049CDB').bold(name));
    console.log("project name is " + chalk.bgHex('#049CDB').bold(name))
})

program.parse()
复制代码

在命令行中运行项目 my-vue create my-app 看一下效果

image.png

具体的样式对照表如下 👇

image.png

3. inquirer 命令行交互工具

更多用法 👉 文档地址

inquirer 在脚手架工具中的使用频率是非常高的,其实在上文脚手架的简单雏形中,我们已经使用到了,这里就不过多介绍了。

4. ora 命令行 loading 动效

更多用法 👉 文档地址

// 自定义文本信息
const message = 'Loading unicorns'
// 初始化
const spinner = ora(message);
// 开始加载动画
spinner.start();

setTimeout(() => {
    // 修改动画样式

    // Type: string
    // Default: 'cyan'
    // Values: 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white' | 'gray'
    spinner.color = 'red';    
    spinner.text = 'Loading rainbows';

    setTimeout(() => {
        // 加载状态修改
        spinner.stop() // 停止
        spinner.succeed('Loading succeed'); // 成功 ✔
        // spinner.fail(text?);  失败 ✖
        // spinner.warn(text?);  提示 ⚠
        // spinner.info(text?);  信息 ℹ
    }, 2000);
}, 2000);
复制代码

命令行是输出效果如下

5. cross-spawn 跨平台 shell 工具

更多用法 👉 文档地址

在脚手架里面,可以用来自动执行 shell 命令,例如:

#! /usr/bin/env node 

const spawn = require('cross-spawn');
const chalk = require('chalk')

// 定义需要按照的依赖
const dependencies = ['vue', 'vuex', 'vue-router'];

// 执行安装
const child = spawn('npm', ['install', '-D'].concat(dependencies), { 
    stdio: 'inherit' 
});

// 监听执行结果
child.on('close', function(code) {
    // 执行失败
    if(code !== 0) {
        console.log(chalk.red('Error occurred while installing dependencies!'));
        process.exit(1);
    }
    // 执行成功
    else {
        console.log(chalk.cyan('Install finished'))   
    }
})
复制代码

同样的在命令行执行一下 my-vue 看一下执行结果

image.png

成功安装 👍

三、搭建自己的脚手架 🏗

了解完基本原理和配套构建的工具后就可以搭建自己的脚手架了 先给我们的脚手架起个名字吧,因本人喜欢玩LOL,所以个人项目名大多是游戏人物,这里就起名为 garen-cli😆(garen---盖伦)

需要实现哪些基本功能:

  1. 通过 gr create <name> 命令启动项目
  2. 询问用户需要选择需要下载的模板
  3. 远程拉取模板文件

搭建步骤拆解:

  1. 创建项目
  2. 创建脚手架启动命令(使用 commander)
  3. 询问用户问题获取创建所需信息(使用 inquirer)
  4. 下载远程模板(使用 download-git-repo)
  5. 发布项目

发布项目

    1. npm login 输入npm 账号 密码 邮箱以及邮箱收到的验证码
    1. npm publish 只要没报错就发布成功了

之后打开npm官网搜索即可查到

项目代码地址:

github.com/yyt520/gare…

四、Yeoman:一个通用的脚手架系统

Yeoman 实际上是三个工具的总和:

  • yo --- 脚手架,自动生成工具
  • grunt、gulp --- 构建工具
  • bower、npm --- 包管理工具 使用 Yeoman 搭建脚手架非常简单,Yeoman 提供了 yeoman-generator 让我们快速生成一个脚手架模板,我们可以通过各类 Generator 实现任何类型的项目搭建。