likes
comments
collection
share

nodejs 开发跨平台 cli 工具

作者站长头像
站长
· 阅读数 17

原文:https://blog.fengjx.com/pages...

在软件开发中有很多重复性或者是繁琐的工作,通过一些命令行工具可以简化我们的日常工作,提高效率。

例如:

随着 nodejs 的发展,已经在各领域都有完善的生态,使用 nodejs 开发命令行工具也是一个不错的选择

直接读源码可查看:https://github.com/fengjx/kit...

如何运行一个 nodejs 脚本

版本1

// hello.js
console.log('hello world')

执行

node hello.js

版本2

// hello.js
#!/usr/bin/env node
console.log('hello world')

执行

chmod 755 hello.js
./hello.js

工程化开发

运行一个 nodejs 脚本非常简单,可以和 shell 脚本一样。但是要实现一个完备的功能,我们通常需要依赖第三方类库。写好的工具提供给别人使用就需要一个发布平台。所以使用 npm 来管理项目是个很好的选择。

除此之外,一个易用的工具,应该给用户提供使用文档,告诉用户有哪些参数可以传,参数含义是什么。如果我们重新开发的话会是一件非常繁琐的事情,好在已经有第三方类库封装了这部分功能。下面是一些封装的比较好的类库。当然也远远不止这些。

  • commander 命令行参数解析
  • inquirer 交互式命令行参数解析
  • shelljs 跨平台 shell 命令
  • pkg node 可执行文件打包工具

更多第三方类库可查看:https://github.com/huaize2020...

以下是个简单 demo,更多用法参考官方文档

bin/hello.js

#!/usr/bin/env node

const { Command } = require('commander')
const inquirer = require('inquirer')

const program = new Command()
program.version('0.0.1')

console.log('hello node cli')

// https://github.com/tj/commander.js
// 解析命令行参数
// hello -d -n fengjx
program.option('-d, --debug', 'debug')
program.option('-n, --name <type>', 'your name')
program.parse(process.argv)
const opts = program.opts()

if (opts.debug) {
  console.log('opts: ', opts)
}

console.log(`hello: ${opts.name}`)

// https://github.com/SBoudrias/Inquirer.js/tree/master/packages/inquirer/examples
// 交互式终端
const questions = [
  {
    type: 'input',
    name: 'username',
    message: "输入账号",
  },
  {
    type: 'password',
    name: 'password',
    message: "输入密码"
  }
]

inquirer.prompt(questions).then((answers) => {
  console.log(JSON.stringify(answers, null, '  '))
})

执行

$ node bin/hello.js -d -n fengjx
hello node cli
opts:  { debug: true, name: 'fengjx' }
hello: fengjx
? 输入账号 fjx
? 输入密码 [hidden]
{
  "username": "fjx",
  "password": "1024"
}

基础框架设计

对于一个命令行工具来说,通常包含以下步骤:

  1. 定义参数
  2. 参数校验&解析
  3. 读取参数,并执行相关逻辑

我们可以封装一个统一的接口,不同的工具实现对应方法,相同的逻辑全都放到入口函数即可,每个命令只需要实现对应接口的方法。

接口Cmd定义

cmd.js

/**
 * 命令接口
 */
class Cmd {

  /**
   * 命令名称
   *
   * @returns string
   */
  actionName() {
  }

  /**
   * 命令参数配置
   * @returns Option[]
   */
  makeOptions() {
  }

  /**
   * 业务逻辑
   * @param {*} opts 参数解析结果
   */
  // eslint-disable-next-line no-unused-vars
  exec(opts) {
  }
}

module.exports = Cmd

完整项目代码: https://github.com/fengjx/kit

打包&安装

功能开发好之后,我们需要发布给别人使用,如果是有 node 环境可以直接使用源码安装,也可以直接打包成一个可执行文件,这样别人使用的时候不需要再安装 node。

通过 npm 全局安装

git clone https://github.com/fengjx/kit.git
cd kit
# 安装依赖
npm i
# 全局安装
npm i -g .
# 测试是否安装成功
kit --help

打包可执行文件

nodejs 的执行需要依赖 v8 引擎,所以需要 node 环境才能运行,pkg 这个工具可以将 node 环境和代码打包到一起(所以打出来的包会比较大 50M 左右),得到一个可执行文件,可以把文件上传到 cdn 提供别人直接下载使用。

package.js中定义了打包命令

"pkg:mac": "pkg . --targets node14-macos-x64 --output ./.dist/kit-macos-64",
"pkg:win": "pkg . --targets node14-win-x64 --output ./.dist/kit-win-64",
"pkg:linux": "pkg . --targets node14-linux-x64 --output ./.dist/kit-linux-64",

不同平台需要指定不同的参数,更多参数可以参考官方文档:https://github.com/vercel/pkg

通过 npm 打包不同平台下的包

npm run pkg:mac # pkg:win or pkg:linux

测试

$ cd .dist
$ ./kit-macos-64 hello --version
1.0.0

$ ./kit-macos-64 --help         
Usage: kit [options] [command]

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

Commands:
  hello [options]
  gl-bcl [options]
  help [command]    display help for command