看了就会的 Node.js 常用三方工具包

2,170 阅读7分钟

前言

之前一篇文章介绍了 Node.js 的三个模块的基础 API,面对文档时不那么抓瞎,基础 API 用习惯了也差不多找到感觉,之后想用啥就可以自己照着文档找就好了。

除了 Node 提供的基础模块之外,我们在开发中必不可少地会用到第三方模块,也就是我们最常见的社区 NPM 包。这篇文章主要就是介绍一些在开发 Node 的时候,常用的一些基础工具包。

两篇文章配合使用,应该可以帮助你上手 Node 开发。

文件系统

这些工具包的功能就是在 Node 本身的 fs 模块基础上提供更加方便的文件系统操作 API。

glob

一句话介绍

glob 是一种文件匹配模式,起源于 Unix,比如我们常见 *.js 匹配所有 js 文件就是使用了 glob 模式。

GitHub 地址:github.com/isaacs/node…

使用方法

glob(pattern, [options], callback)glob 方法接收三个参数:

  • pattern: 匹配规则字符串
  • options: 配置项(可选)
  • callback: 回调函数 (error, files) => {}
    • error: 错误信息,如果不存在则为成功
    • matches: 匹配文件数组

其中 options 是可选项:文档,可以不传,直接将回调函数放在第二个参数。

如果不想使用回调的方式,可以使用同步方法 glob.sync(pattern, options),用法一致,返回值即是匹配文件数组。

举例

当前文件目录如下:

.
├── a
│   ├── a.css
│   ├── a.js
    ├── .eslintrc.js
│   └── b
│       ├── b.css
│       └── b.js
├── index.js
├── package.json

index.js 代码如下:

const glob = require("glob")

glob("a/**/*.js", (error, matches) => {
  if (!error) {
    console.log(matches);
  }
});

try {
  const files = glob.sync("a/**/*.js");
  console.log(files);
} catch (e) {}

输出如下:

[ 'a/a.js', 'a/b/b.js' ]

是不是发现 .eslintrc.js 文件并没有被匹配到。默认情况下,glob 不会匹配以 . 开头的文件,需要我们在配置项中打开:

const glob = require("glob")

glob("a/**/*.js", { dot: true }, (error, matches) => {
  if (!error) {
    console.log(matches);
  }
});
// [ 'a/.eslintrc.js', 'a/a.js', 'a/b/b.js' ]

globby

一句话介绍

globby 是增强型的 glob,提供了 Promise 的封装。最终要的是它支持多模式匹配,相比于 glob 只能传入一个 pattern 字符串,globby 支持传入一个 pattern 数组。

GitHub 地址:github.com/sindresorhu…

使用方法

globby(patterns, options?)globby 接收两个参数,返回 Promise

  • patterns: 匹配规则数组
  • options: 配置项

举例

当前文件目录如下:

.
├── a
│   ├── a.css
│   ├── a.js
    ├── .eslintrc.js
│   └── b
│       ├── b.css
│       └── b.js
├── index.js
├── package.json

index.js 代码如下:

const globby = require('globby');

(async () => {
  const files = await globby(['a/**/*.js', 'a/**/*.css'], { dot: true });
  console.log(files);
})();

输出如下:

[ 'a/.eslintrc.js', 'a/a.js', 'a/b/b.js', 'a/a.css', 'a/b/b.css' ]

fs-extra

一句话介绍

Node 内置了 fs 模块供开发者和文件系统交互,但是用过的同学都知道,它的能力还是挺有限的。所以,在 fs 的基础上,社区提供了 fs-extra 工具包增强文件系统交互,并且提供了 Promise 的调用方式。

GitHub 地址:github.com/jprichardso…

举例

这里介绍几个最常见的:

const fse = require('fs-extra');

(async () => {
  // 确认目录是否存在,如果不存在会创建目录
  await fse.ensureDir('./a');

  // 复制文件
  await fse.copy('./a/a.js', './a/aa.js');

  // 读 JSON 文件
  const aJSON = await fse.readJSON('./a/a.json');
  console.log(typeof aJSON, aJSON);

  // 写 JSON 文件
  await fse.writeJSON('./a/aa.json', { a: 1 }, { spaces: 2 });

  // 写 JSON 文件,如果目录不存在会创建
  await fse.outputJson('./c/aa.json', { a: 1 }, { spaces: 2 });

  // 删文件
  await fse.remove('./a/aa.json');
})();

执行命令

这几个 NPM 包的功能主要就是会用于执行一些系统命令,比如 npm installgit clone 等等。

shelljs

一句话介绍

这个包的作用就和它的名字一样,用 js 来实现 shell 命令。

GitHub 地址:github.com/shelljs/she…

使用方法

可以通过 shelljs 提供的 exec 命令同步地执行任意的 shell 命令,返回值中的 code 标识是否成功执行,比如:

const shell = require('shelljs');

if (shell.exec('git init .').code === 0) {
  console.log('Git 初始化成功');
}

除了 exec 之外,shelljs 也提供了一些常用 shell 命令的包装,比如 whichecho 等,比如:

const shell = require('shelljs');

shell.echo('Hello Shelljs');

举例

来看两个 shelljs 的常见用法。

const shell = require('shelljs');

// 判断是否有相关开发环境
function hasGitNpm() {
  if (!shell.which('git')) {
    console.log('Sorry, this script requires git');
    shell.exit(1);
  }

  if (!shell.which('npm')) {
    console.log('Sorry, this script requires npm');
    shell.exit(1);
  }
}

hasGitNpm();

// 安装 npm 包
function installPkg(pkg, type) {
  const npm = shell.which('npm');
  if (!npm) {
    console.log('请先安装 npm');
    return;
  }
  const { code } = shell.exec(
    `${npm.stdout} install ${pkg} ${type || '--save'}`
  );
  if (code) {
    console.log(`安装 ${pkg} 失败,请手动安装`);
  }
}

installPkg('lodash');

cross-spawn

一句话介绍

在 Node 中,可以通过 child_process 模块来创建子进程,并且通过 child_process.spawn 方法来使用指定的命令行参数创建新进程,执行完之后返回执行结果。而 cross-spawn 包就是提供了关于 spawn 函数的跨平台写法,不用开发者处理跨平台的逻辑。

GitHub 地址:github.com/moxystudio/…

使用方法

用法和 child_process.spawn(command[, args][, options]) 保持一致:

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

const child = spawn('npm', ['install'], { stdio: 'inherit' });

举例

看一个比较常见的 cross-spawn 用法:

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

// 安装全部依赖
spawn.sync('npm', ['install'], { stdio: 'inherit' });

// 安装指定依赖
spawn.sync('npm', ['install', 'lodash', '--save'], { stdio: 'inherit' });

rimraf

一句话介绍

相当于在命令行中执行了 rm -rf,咳咳,是不是有点危险啊。

GitHub 地址:hhttps://github.com/isaacs/rimraf

使用方法

rimraf(f, [opts], callback)rimraf 方法接收三个参数:

  • f: glob 匹配规则
  • opts: 配置项,可选
  • callback: 回调函数

当然,也可以使用 rimraf.sync 同步方法。

const rimraf = require('rimraf');

rimraf('./a/aa.js', error => {
  if (!error) {
    console.log('删除成功');
  }
});

除了在 Node 中用,在 package.jsonscripts 中也会经常看到这个工具,比如:

{
  "scripts": {
    "build": "rimraf build && npm run build"
  }
}

网络请求

这里主要列了两个目前正在用的网络请求的包。

node-fetch

一句话介绍

相当于在 Node 上使用 Fetch。

GitHub 地址:github.com/node-fetch/…

使用方法

就举个简单例子,其它的看文档就好了:

const fetch = require('node-fetch');

const response = await fetch('https://api.github.com/users/github');
const data = await response.json();

console.log(data);

axios

一句话介绍

axios 就不用介绍了,写前端的同学都知道,用起来也很方便。

GitHub 地址:github.com/axios/axios

使用方法

const axios = require('axios');

axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

小工具

这里就列一堆用得上的小工具吧,按需用。

open

一句话介绍

open 包可以让你在代码中打开网页、图片等等。比如你经常 npm start 启动项目的时候,是不是会自动唤起浏览器打开一个 localhost 的页面,就是通过 open 包实现的。

GitHub 地址:github.com/sindresorhu…

使用方法

const open = require('open');

await open('http://localhost:8080');

http-server

一句话介绍

http-server 包一般安装在全局使用,可以在本地任意目录 0 配置启动一个 HTTP 服务,一般在本地开发和测试的时候会经常用到。比如,使用 npm build 打包构建出构建产物之后,可以本地执行 http-server build 启动一个服务。

GitHub 地址:github.com/http-party/…

path-to-regexp

一句话介绍

顾名思义,path-to-regexp 是将指定 path 转换成一个正则表达式的工具,一般在接口路径匹配的时候会用到。

GitHub 地址:github.com/pillarjs/pa…

使用方法

比如我们的 API 的路径有很多,其中有一部分是对外开放的 API,它的路径是 /openapi/* 的,可以这样匹配:

const { pathToRegexp } = require('path-to-regexp');

console.log(pathToRegexp('/openapi/:key'));

输出结果为:

/^\/openapi(?:\/([^\/#\?]+?))[\/#\?]?$/i

url-join

一句话介绍

url-join 包可以非常方便地操作一个 url,拼接任意参数。

GitHub 地址:github.com/jfromaniell…

使用方法

假设我们需要动态地拼接参数,可以这样:

const urlJoin = require('url-join');

console.log(urlJoin('http://www.google.com', 'a', '/b/cd', '?foo=123'));

输出结果为:

http://www.google.com/a/b/cd?foo=123

semver

一句话介绍

NPMsemver 规范相关的工具包,判断版本啥的。

GitHub 地址:github.com/npm/node-se…

使用方法

const semver = require('semver')

// 判断是否符合规范
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
// 判断 a 版本是否比 b 版本高
semver.gt('1.2.3', '9.8.7') // false
// 判断 a 版本是否比 b 版本低
semver.lt('1.2.3', '9.8.7') // true
// 判断符合某个版本范围的最低版本
semver.minVersion('>=1.0.0') // '1.0.0'

CLI 相关

见之前的文章: 实现 CLI 常用工具包 - 终端交互相关(问卷、彩色文字、loading、进度条)

总结

这篇文章到这里就结束了,本文整理了一些在 Node 开发时常用的 NPM 包,希望能够帮到你。但是社区之大,功能强大的 NPM 包远不止这些,可以自行探索。

需要使用某个功能的 NPM 包时,可以在 NPM 官网或者 GitHub 上搜索:

NPM 官网www.npmjs.com/


更多文章欢迎关注公众号『前端试炼』,获取前端精选文章。