看了就会的 Node.js 常用三方工具包
👆 点击上方卡片关注
前言
之前一篇文章介绍了 Node.js 的三个模块的基础 API,面对文档时不那么抓瞎,基础 API 用习惯了也差不多找到感觉,之后想用啥就可以自己照着文档找就好了。
除了 Node 提供的基础模块之外,我们在开发中必不可少地会用到第三方模块,也就是我们最常见的社区 NPM 包。这篇文章主要就是介绍一些在开发 Node 的时候,常用的一些基础工具包。
两篇文章配合使用,应该可以帮助你上手 Node 开发。
文件系统
这些工具包的功能就是在 Node 本身的 fs
模块基础上提供更加方便的文件系统操作 API。
glob
一句话介绍
glob
是一种文件匹配模式,起源于 Unix
,比如我们常见 *.js
匹配所有 js
文件就是使用了 glob
模式。
GitHub 地址:https://github.com/isaacs/node-glob[1]
使用方法
glob(pattern, [options], callback)
,glob
方法接收三个参数:
pattern: 匹配规则字符串 options: 配置项(可选) callback: 回调函数 (error, files) => {}
error: 错误信息,如果不存在则为成功 matches: 匹配文件数组
其中 options
是可选项:文档[2],可以不传,直接将回调函数放在第二个参数。
如果不想使用回调的方式,可以使用同步方法 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 地址:https://github.com/sindresorhus/globby[3]
使用方法
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 地址:https://github.com/jprichardson/node-fs-extra[4]
举例
这里介绍几个最常见的:
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 install
、git clone
等等。
shelljs
一句话介绍
这个包的作用就和它的名字一样,用 js
来实现 shell
命令。
GitHub 地址:https://github.com/shelljs/shelljs[5]
使用方法
可以通过 shelljs
提供的 exec
命令同步地执行任意的 shell
命令,返回值中的 code
标识是否成功执行,比如:
const shell = require('shelljs');
if (shell.exec('git init .').code === 0) {
console.log('Git 初始化成功');
}
除了 exec
之外,shelljs
也提供了一些常用 shell
命令的包装,比如 which
、echo
等,比如:
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 地址:https://github.com/moxystudio/node-cross-spawn[6]
使用方法
用法和 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[7]
使用方法
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.json
的 scripts
中也会经常看到这个工具,比如:
{
"scripts": {
"build": "rimraf build && npm run build"
}
}
网络请求
这里主要列了两个目前正在用的网络请求的包。
node-fetch
一句话介绍
相当于在 Node 上使用 Fetch。
GitHub 地址:https://github.com/node-fetch/node-fetch[8]
使用方法
就举个简单例子,其它的看文档就好了:
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 地址:https://github.com/axios/axios[9]
使用方法
const axios = require('axios');
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
小工具
这里就列一堆用得上的小工具吧,按需用。
open
一句话介绍
open
包可以让你在代码中打开网页、图片等等。比如你经常 npm start
启动项目的时候,是不是会自动唤起浏览器打开一个 localhost
的页面,就是通过 open
包实现的。
GitHub 地址:https://github.com/sindresorhus/open[10]
使用方法
const open = require('open');
await open('http://localhost:8080');
http-server
一句话介绍
http-server
包一般安装在全局使用,可以在本地任意目录 0 配置启动一个 HTTP 服务,一般在本地开发和测试的时候会经常用到。比如,使用 npm build
打包构建出构建产物之后,可以本地执行 http-server build
启动一个服务。
GitHub 地址:https://github.com/http-party/http-server[11]
path-to-regexp
一句话介绍
顾名思义,path-to-regexp
是将指定 path
转换成一个正则表达式的工具,一般在接口路径匹配的时候会用到。
GitHub 地址:https://github.com/pillarjs/path-to-regexp[12]
使用方法
比如我们的 API 的路径有很多,其中有一部分是对外开放的 API,它的路径是 /openapi/*
的,可以这样匹配:
const { pathToRegexp } = require('path-to-regexp');
console.log(pathToRegexp('/openapi/:key'));
输出结果为:
/^\/openapi(?:\/([^\/#\?]+?))[\/#\?]?$/i
url-join
一句话介绍
用 url-join
包可以非常方便地操作一个 url,拼接任意参数。
GitHub 地址:https://github.com/jfromaniello/url-join[13]
使用方法
假设我们需要动态地拼接参数,可以这样:
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
一句话介绍
NPM
的 semver
规范相关的工具包,判断版本啥的。
GitHub 地址:https://github.com/npm/node-semver[14]
使用方法
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 官网:https://www.npmjs.com/[15]
参考资料
https://github.com/isaacs/node-glob: https://github.com/isaacs/node-glob
[2]文档: https://github.com/isaacs/node-glob#options
[3]https://github.com/sindresorhus/globby: https://github.com/sindresorhus/globby
[4]https://github.com/jprichardson/node-fs-extra: https://github.com/jprichardson/node-fs-extra
[5]https://github.com/shelljs/shelljs: https://github.com/shelljs/shelljs
[6]https://github.com/moxystudio/node-cross-spawn: https://github.com/moxystudio/node-cross-spawn
[7]hhttps://github.com/isaacs/rimraf: https://github.com/isaacs/rimraf
[8]https://github.com/node-fetch/node-fetch: https://github.com/node-fetch/node-fetch
[9]https://github.com/axios/axios: https://github.com/axios/axios
[10]https://github.com/sindresorhus/open: https://github.com/sindresorhus/open
[11]https://github.com/http-party/http-server: https://github.com/http-party/http-server
[12]https://github.com/pillarjs/path-to-regexp: https://github.com/pillarjs/path-to-regexp
[13]https://github.com/jfromaniello/url-join: https://github.com/jfromaniello/url-join
[14]https://github.com/npm/node-semver: https://github.com/npm/node-semver
[15]https://www.npmjs.com/: https://www.npmjs.com/
交流讨论
欢迎关注公众号「大海我来了」,公众号平时会分享一些实用或者有意思的东西,发现代码之美。专注深度和最佳实践,希望打造一个高质量的公众号。
❤️
🙏
如果觉得这篇文章还不错
来个【分享、点赞、在看】三连吧
让更多的人也看到