npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

txm-cli-demo

v1.0.0

Published

## 初始化

Downloads

2

Readme

脚手架实现过程

初始化

初始化一个项目目录并初始化package.json

mkdir txm-cli
cd txm-cli
yarn init -y

新建bin目录,在bin目录下创建入口文件cli.js

cli应该必须要在入口文件声明

#!/usr/bin/env node

如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755 chmod 755 cli.js

我们现在cli.js文件中输出一段话

#!/usr/bin/env node
console.log('cli init')

然后配置package.json文件中的bin字段

{
  "name": "txm-cli",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "bin": {
    "txm": "bin/cli.js"
  }
}

键代表我们要执行的cli命令,值是入口文件的位置

执行yarn link将命令连接到全局

执行bin中配置的命令测试,例如:

txm

输出如下:

cli init

说明我们的基本配置就完成了,接下来就是完成具体的功能了

命令行参数设计

txm-cli -h|--help 查看使用帮助
txm-cli -v|--version 查看版本号
txm-cli list 列出所有可用模板
txm-cli init <template name> <project name> 基于指定的模板进行项目初始化

使用 commander 模块处理命令行

我们要做的就是

  1. 获取用户输入的参数
  2. 根据不同的参数生成不同的模板

nodejs中获取用户输入的命令可以使用process.argv来获取,它拿到的是一个数组,然后数组里面的值是用户在命令行输入的参数,如果我们自己来判断这个参数还是比较麻烦的,所以这里借助 commander这个模块来帮助我们处理参数

首先去安装commander

yarn add commander

commander的使用也是比较简单的,使用教程

下面我们就来使用一下这个包

#!/usr/bin/env node

const { program } = require('commander');

program
  .version('0.1.0')

program.parse(process.argv);

然后我们在命令行中输入

txm -V

输出结果:

0.1.0

这就说明这个包可以正常使用了,接下来就来配置一下我们自己的命令

因为help命令它自己就有,所以我们不用配置,我们先来配置一下init命令

// 配置init命令
program
  .command('init <template> <project>') // 尖括号代表必输项,第一个参数是模板名称,第二个参数是项目名称
  .description('init project...') // 执行命令时的描述信息
  .action(function (templateName, projectName) { // 接收到用户输入的参数后要做的事情
    // 根据模板名称下载对应的模板到本地并起名为 projectName
    console.log(templateName, projectName)
  })

执行一下

txm init webpack my-project

输出结果:

webpack my-project

init命令配置好了之后我们先去配置一下list命令,具体的实现我们等下在去做

// 配置 list 命令
program
  .command('list')
  .description('list all templates')
  .action(() => {
    console.log(`sample     sample模板`)
    console.log(`webpack    webpack模板`)
    console.log(`vue        vue模板`)
    console.log(`react      react模板`)
  })

我们简单的配置一下,具体的一会儿再来实现

执行

txm list

输出结果:

sample     sample模板
webpack    webpack模板
vue        vue模板
react      react模板

到这里我们的命令就配置好了

准备模板

github上创建三个仓库,一个仓库里面放vue的基础模板,一个仓库放react的基础模板,一个就准备一个简单的项目结构,然后我们修改一下我们的list命令

三个模板仓库的地址

https://github.com/tangxinming0310/txm-vue-tempalte
https://github.com/tangxinming0310/txm-react-template
https://github.com/tangxinming0310/txm-sample-tempalte

我们在cli.js中去定义我们的模板仓库

const templates = {
  'sample': {
    url: 'https://github.com/tangxinming0310/txm-sample-template',
    desc: 'sample-template'
  },
  'react': {
    url: 'https://github.com/tangxinming0310/txm-react-template',
    desc: 'react-template'
  },
  'vue': {
    url: 'https://github.com/tangxinming0310/txm-vue-tempalte',
    desc: 'vue-template'
  }
}

然后在list命令中去修改一下

// 配置 list 命令
program
  .command('list')
  .description('list all templates')
  .action(() => {
    Object.keys(templates).forEach(key => {
      console.log(`${key}      ${templates[key].desc}`)
    })
  })

执行:

txm list

输出结果:

sample      sample-template
react      react-template
vue      vue-template

下载模板

模板准好了之后,我们就需要根据用户的输入然后去获取模板地址并下载对应的模板

下载模板我们需要借助一个 download-git-repo的库

先安装这个库

yarn add download-git-repo

使用方式:

// 第一参数是下载地址 规则为 => [github]:[账户名]/[仓库名]
// 第二参数是项目的名称
download(downloadUrl, projectName, { clone: true }, (err) => {
    if (err) {
        console.log(`download ${templateName} template  failed`)
    } else {
        console.log('download success')
    }
})

所以这里我们对templates添加一个下载地址

const templates = {
  'sample': {
    url: 'https://github.com/tangxinming0310/txm-sample-template',
    downloadUrl: 'https://github.com:tangxinming0310/txm-sample-template',
    desc: 'sample-template'
  },
  'react': {
    url: 'https://github.com/tangxinming0310/txm-react-template',
    downloadUrl: 'https://github.com:tangxinming0310/txm-react-template',
    desc: 'react-template'
  },
  'vue': {
    url: 'https://github.com/tangxinming0310/txm-vue-tempalte',
    downloadUrl: 'https://github.com:tangxinming0310/txm-vue-tempalte',
    desc: 'vue-template'
  }
}

然后去修改我们的init命令


// 配置 init 命令
program
  .command('init <template> <project>') // 尖括号代表必输项,第一个参数是模板名称,第二个参数是项目名称
  .description('init project...') // 执行命令时的描述信息
  .action(function (templateName, projectName) { // 接收到用户输入的参数后要做的事情
    // 根据模板名称下载对应的模板到本地并起名为 projectName
    // 根据用户输入获取对应的模板地址
    const { downloadUrl } = templates[templateName]
    // 下载模板
    download(downloadUrl, projectName, { clone: true }, (err) => {
      if (err) {
        console.log(`download ${templateName} template  failed`)
      } else {
        console.log('download success')
      }
    })
  })

在命令行执行:

txm vue vue-demo

结果:可以看到在当前目录下生成了一个 vue-demo 的文件夹,里面就是我们仓库里面的模板文件

命令行交互

模板下载好了之后我们在增加一下命令行交互来增强用户体验,比如说package.json文件中的一些信息我们可以让用户自己来填写,例如author,name

这里我们就需要使用到模板引擎了

我们先对仓库中的package.json文件做一些改写,我们把nameauthordescription这个三个字段改写成模板引擎的方式

  "name": "<%= name %>",
  "author": "<%= author %>",
  "description": "<%= description %>"

然后我们使用ejs作为模板引擎

yarn add ejs

命令行交互这里需要用到inquirer库,先安装

yarn add inquirer

然后我们去引入几个模块

const fs = require('fs')
const path = require('path')
const inquirer = require('inquirer')
const ejs = require('ejs')

因为我们需要读取package.json文件,所以需要用到fspath两个库

然后我们在项目模板下载完成后

  1. 向用户发起询问
  2. 根据用户的回答使用模板引擎把用户的值解析到 package.json
  3. 解析完成后,把解析之后结果重新写入 package.json

根据这个步骤我们去修改一下我们的init命令

// 配置 init 命令
program
  .command('init <template> <project>') // 尖括号代表必输项,第一个参数是模板名称,第二个参数是项目名称
  .description('init project...') // 执行命令时的描述信息
  .action(function (templateName, projectName) { // 接收到用户输入的参数后要做的事情
    // 根据模板名称下载对应的模板到本地并起名为 projectName
    // 根据用户输入获取对应的模板地址
    const { downloadUrl } = templates[templateName]
    download(downloadUrl, projectName, { clone: true }, (err) => {
      if (err) {
        return console.log(`download ${templateName} template  failed`)
      }
      // 发起命令行交互
      inquirer.prompt([
        {
          type: 'input',
          name: 'name',
          message: 'Project name?',
          default: projectName
        },
        {
          type: 'input',
          name: 'description',
          message: 'Project description?'
        },
        {
          type: 'input',
          name: 'author',
          message: 'Project author?'
        }
      ])
      .then(answers => {
        // package.json 文件的路径
        const packagePath = path.join(projectName, 'package.json');
        // 使用模板引擎把用户的值解析到 package.json 中
        ejs.renderFile(packagePath, answers, (err, result) => {
          if (err) throw err
          // 解析完成后,把解析之后结果重新写入 package.json
          fs.writeFileSync(packagePath, result)
          console.log(`${templateName} template init success`)
        })
      })
    })
  })

然后我们去测试一下

txm vue vue-demo

然后可以看到命令行会发出一些问题交互,我们输入信息后,打开vue-demo文件夹,查看package.json文件,可以看到其中的表达式已经全部被替换成我们输入的信息了

增加下载动画

现在我们的cli工具有了,但是在下载模板的时候是感知不到的,这一点体验不是很好,我们去增加一个下载的loading动画,借助ora这个库来实现

安装

yarn add ora

基本的使用方式

const ora = require('ora')
const spinner = ora('downloading...')
spinner.start()
spinner.fail() // 下载失败
spinner.succeed() // 下载成功

增加文字颜色和小图标

然后我们可以通过chalk这个库为打印的信息加上样式,比如成功为绿色,失败为红色,可以使得我们的终端效果更加友好

yarn add chalk

基本使用,它有很多种颜色,我们需要什么颜色就使用什么颜色就好了

console.log(chalk.red(err))
console.log(chalk.green('success'))

使用log-symbols来增加小图标

yarn add log-symbols

使用方式就是在输出的第一个位置直接使用他对应的图标就好了

console.log(logSymbols.success, chalk.green('success'))

完整的cli代码

请查看bin目录下cli.js文件