zx.js 轻松上手教程

1,123 阅读2分钟

Bash 是 Linux 和 Mac 的默认 Shell 解释器, 但是作为前端开发书写 Bash 脚本需要单独学习 Bash 语法, 无疑增加了上手成本, 当然我们可以用 Node.js 编写脚本, 但实际使用中并没有那么方便。而今天介绍的 zx.js 可以协助我们使用 Node.js 更高效的编写 Shell 脚本

直接使用 Node.js 编写脚本有很多不方便的地方:

  1. 调用 Unix 命令(mkdir, cd, ls...)需要通过 child_process 模块;
  2. 使用第三方库需要安装依赖并手动引入, 依赖越来越多, 导致脚本文件变成了一个项目 ...

1. 使用 zx.js 注意事项

  • node version >= 16.0.0
  • 文件后缀可以是 .mjs, .js
    • .mjs 文件后缀(推荐): 可在顶层使用 await
    • .js 文件后缀: 需将脚本包裹在 void async function () {...}(), 方便使用 await
npm i -g zx@7 # 安装 zx

2. 简单使用

编辑一个简单脚本: clone 一个项目, 安装依赖

// index.mjs

#!/usr/bin/env zx

import { spinner } from 'zx/experimental'

const inputName = await question("请输入你的项目目录:");// 获取用户输入的项目目录
const dirname = inputName || "default-name";// 默认目录名称

// 执行命令(同时展示loading)
await spinner('创建项目中...', async () => {
  await $`git clone git@github.com:wywppkd/umi-with-fabric.git ${dirname}`
  cd(dirname);// 进入项目目录
})

await $`npm install`;// 安装依赖

执行脚本

# 方式1
$ chmod +x ./index.mjs # 设置执行权限
$ ./index.mjs

# 方式2
$ zx ./index.mjs

3. zx 常用内置函数

#!/usr/bin/env zx

// 执行任意 Unix 命令
await $`ls`;
await $`cat package.json | grep version`; // 查看文件指定内容
await $`mkdir src`; // 创建目录
await $`pwd`; // 输出当前目录
await $`exit 1` // 退出程序

// echo: 代替 console.log 输出日志
echo(__dirname);// 打印当前目录绝对路径
echo(__filename);// 打印当前文件绝对路径

cd("./tmp/"); // 切换目录
await sleep(10000); // 等待10秒

// 基于 Node.js 的 readline 模块的封装
const fruit = await question('最好吃的水果是什么? ', {
  choices: ['苹果', '香蕉', '西瓜'],// 点击tab, 提示答案列表
})

$.verbose = false; // 关闭日志
$.verbose = true; // 开启日志

// 发送请求方法(基于 node-fetch 封装方法)
let res = await fetch("http://rap2api.taobao.org/app/mock/230933/user/info").then(res => res.json());
if(res.errcode === 0){
  console.log(res)
}

4. zx 实验性函数

zx 同时提供了一些实验性函数, 需要显示引入后才能使用

#!/usr/bin/env zx

import { spinner } from 'zx/experimental'
await spinner('working...', () => $`mkdir src`) // 展示 loading 效果

5. zx 内置包

内置依赖包无需导入即可直接使用

  • zx 内置包: 包括一些 Node 核心包和其他 npm 包
    • chalk: 用于输出彩色的内容
    • fs-extra: fs 的强化版
    • globby: 用于模糊搜索文件名
    • minimist: 用于处理命令行参数
    • node-fetch: 发送请求库
    • os: 用于获取系统信息
    • path: 用于对路径做处理
    • ...github.com/google/zx#p…
// 使用 chalk 包
echo(chalk.blue("Hello Chalk!"));

// 使用 fs-extra 包
const content = await fs.readFile("./package.json", "utf8");
echo(content);

// 使用 os 包
echo(os.homedir());

// minimist: 获取命令行参数, 假设执行命令: zx ./index.mjs app1 -port 8080
echo(argv)// { _: [ './index.mjs', 'app1' ], port: 8080 }
echo(argv._[1]) // app1, 指定索引的参数值
echo(argv.port) // 8080, 指定参数port

// ...

6. zx 使用第三方包

使用第三方包需要安装依赖, 引包后才能使用

npm i inquirer
#!/usr/bin/env zx
import inquirer from "inquirer";

const env = await inquirer.prompt([
  {
    type: "list",
    name: "env",
    message: "请输入",
    choices: ["dev", "test", "prod"],
  },
]);
console.log("env", env);