看了就會的 Node.js 三大基礎模塊經常使用 API

爆肝日更    前端面試    前端工程化

👆  點擊上方卡片關注html

在平常使用 Node 進行開發的時候,會使用到一些文件系統、路徑操做等基礎 API,這裏整理一下,方便你們理解和直接使用。
前端

這裏只介紹最經常使用的那些,不是全部哈,想要看更全的,直接看官方文檔[1]就 OK。vue

儘可能不廢話,多上代碼。node

Process 模塊

先介紹 process 模塊,它提供了當前 Node 進程相關的全局環境信息。在後面的 API 中被用到。linux

// 內置模塊,直接使用
const process = require('process');

process.cwd()

這是一個函數,返回當前 Node 進程執行的目錄,舉例一個常見的場景:webpack

一個 Node 模塊 A 經過 NPM 發佈,項目 B 中使用了模塊 A。在 A 中須要操做 B 項目下的文件時,就能夠用 process.cwd() 來獲取 B 項目的路徑。web

const cwd = process.cwd(); // 輸出:/Users/xiaolian/Code/node-api-test

process.argv

在終端經過 Node 執行命令的時候,經過 process.argv 能夠獲取傳入的命令行參數,返回值是一個數組:面試

  • 0: Node 路徑(通常用不到,直接忽略)
  • 1: 被執行的 JS 文件路徑(通常用不到,直接忽略)
  • 2~n: 真實傳入命令的參數**

因此,咱們只要從 process.argv[2] 開始獲取就行了。通常都是這樣用vue-cli

const args = process.argv.slice(2);

直接獲取咱們想要的參數。json

process.env

返回一個對象,存儲當前環境相關的全部信息,通常不多直接用到。

通常咱們會在 process.env 上掛載一些變量標識當前的環境。好比最多見的用 process.env.NODE_ENV 區分 developmentproduction。在 vue-cli 的源碼中也常常會看到 process.env.VUE_CLI_DEBUG 標識當前是否是一 DEBUG 模式。

這裏提一個 webpack 的插件 DefinePlugin[2],在平常的構建流程中,咱們常常會經過這個插件來注入不一樣的全局變量,從而執行不一樣的構建流程,而且代碼中的 process.env.xxx 會被替換成具體的值,在 Terser 壓縮階段會將 deadCode 移除,優化代碼體積。

process.platform

這個用的很少,返回當前系統信息,枚舉值以下:

console.log(process.platform);

// 'aix'
// 'darwin'  - macOS
// 'freebsd'
// 'linux' - linux
// 'openbsd'
// 'sunos'
// 'win32' - windows

Path 模塊

// 內置模塊,直接使用
const path = require('path');

Node 中幾乎路徑相關的操做都會使用這個模塊。

這裏就說 5 個最經常使用的:

path.join(...paths)

path.join 做用是將傳入的多個路徑拼成一個完整的路徑。

const dPath = path.join('template''aaa''bbb''ccc''d.js');
// 輸出: template/aaa/bbb/ccc/d.js

來看一個很是常見的場景,咱們須要獲取當前項目的 package.json 文件,就能夠這樣獲取它的路徑:

const pkgPath = path.join(process.cwd(), './package.json');
// 輸出: /Users/xiaolian/Code/node-api-test/package.json

path.join 能夠傳入任意個路徑,好比:

['package.json''README.md'].forEach(fileName => {
  const templateFilePath = path.join(process.cwd(), 'template', fileName);
  console.log(templateFilePath);
});
// 輸出: /Users/xiaolian/Code/node-api-test/template/package.json
// 輸出: /Users/xiaolian/Code/node-api-test/template/README.md

path.resolve(...paths)

path.resovlepath.join 的區別在於它的做用是將傳入的多個路徑和當前執行路徑拼接成一個完整的絕對路徑。

假設我如今 index.jsscripts 目錄下,而後我在根目錄下執行 node scripts/index.js,它的代碼以下:

const dPath = path.resolve('aaa''bbb''ccc''d.js');
// 輸出:  /Users/xiaolian/Code/node-api-test/aaa/bbb/ccc/d.js

通常狀況下,當 path.resolve 的第一個參數爲 ./ 時,能夠直接理解和 path.join(processs.cwd(), '') 表現一致。

path.basename(path[, ext])

path.basename 返回指定 path 最後一個路徑名,其中第二個參數 ext 可選,表示文件擴展名。好比:

console.log(path.basename('scripts/index.js'));  // index.js
console.log(path.basename('scripts/index.js''.js'));  // 匹配到 .js,返回 index
console.log(path.basename('scripts/index.js''.json'));  // 沒匹配到,返回 index.js

path.dirname(path)

path.basename 對應,返回指定 path 最後一個路徑名以前的路徑。好比:

console.log(path.basename('scripts/index.js'));  // scripts
console.log(path.basename('scripts/hook/index.js'));  // scripts/hook

path.extname(path)

path.basename 對應,返回指定 path 最後一個路徑名的文件擴展名(含小數點 .)。好比:

console.log(path.basename('scripts/index.js'));  // .js
console.log(path.basename('README.md'));  // .md

對比

最後再來對比一下各個路徑相關的 API 的區別。

項目 A 的目錄結構以下:

├── scripts
│   └── index.js
├── src
│   └── index.js
├── package.json
├── README.md

scripts/index.js 的代碼以下:

const path = require('path');

console.log(path.join('package.json'));
console.log(path.resolve('package.json'));
console.log(path.join('src''index.js'));
console.log(path.resolve('src''index.js'));
console.log(path.join(process.cwd(), 'package.json'));
console.log(path.resolve('./''package.json'));
console.log(__filename);
console.log(__dirname);

而後,咱們在項目 A 的根目錄下執行 node scripts/index.js,結果以下:

-> node scripts/index.js
package.json
/Users/xiaolian/Code/A/package.json
src/index.js
/Users/xiaolian/Code/A/src/index.js
/Users/xiaolian/Code/A/package.json
/Users/xiaolian/Code/A/package.json
/Users/xiaolian/Code/A/scripts/index.js
/Users/xiaolian/Code/A/scripts

品,仔細品,它們有什麼區別。

我的而言,通常仍是習慣用 path.join(process.cwd(), 'xxx')

File System 模塊

// 內置模塊,直接使用
const fs = require('fs');

文件系統相關操做的模塊,除了 fs 以外,咱們還常常用到 fs-extra,後面會介紹。

這個模塊在平時的 Node 開發中會被大量使用,這裏簡單列幾個,其它的仍是看文檔哈:https://nodejs.org/dist/latest-v14.x/docs/api/fs.html[3]

fs 模塊的 API 默認都是異步回調的形式,若是你想使用同步的方法,有兩種解決方法:

  1. 使用 Node 提供的同步 API: xxxSync,也就是在 API 的後面加一個 Sync 後綴,它就是一個同步方法了(具體仍是須要查文檔哈,是否有提供同步 API)
  2. 包裝成一個 Promise 使用

fs.stat(path[, options], callback)

fs.stat() 返回一個文件或者目錄的信息。

const fs = require('fs');

fs.stat('a.js'function(err, stats{
  console.log(stats);
});

其中包含的參數有不少,介紹幾個比較經常使用的:

export interface StatsBase<T> {
  isFile(): boolean;                 // 判斷是不是一個文件
  isDirectory(): boolean;            // 判斷是否一個目錄

  size: T;                           // 大小(字節數)
  atime: Date;                       // 訪問時間
  mtime: Date;                       // 上次文件內容修改時間
  ctime: Date;                       // 上次文件狀態改變時間
  birthtime: Date;                   // 建立時間
}

通常咱們會使用 fs.stat 來取文件的大小,作一些判斷邏輯,好比發佈的時候能夠檢測文件大小是否符合規範。在 CLI 中,常常須要獲取一個路徑下的全部文件,這時候也須要使用 fs.stat 來判斷是目錄仍是文件,若是是目錄則繼續遞歸。固然,如今也有更方便的 API 能夠完成這個工做。

同步方法

const fs = require('fs');

try {
  const stats = fs.statSync('a.js');
catch(e) {}

fs.readdir(path[, options], callback)

fs.readdir(path) 獲取 path 目錄下的文件和目錄,返回值爲一個包含 filedirectory 的數組。

假設當前目錄爲:

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

執行如下代碼:

const fs = require('fs');

fs.readdir(process.cwd(), function (error, files{
  if (!error) {
    console.log(files);
  }
});

返回值爲:

'a',
  'index.js',
  'package.json' ]

能夠看到這裏只返回了根目錄下的文件和目錄,並無去深度遍歷。因此若是須要獲取全部文件名,就須要本身實現遞歸。

同步方法

const fs = require('fs');

try {
  const dirs = fs.readdirSync(process.cwd());
catch(e) {}

fs.readFile(path[, options], callback)

文件讀取的 API,經過 fs.readFile 能夠獲取指定 path 的文件內容。

入參以下:

  • 第一個參數: 文件路徑
  • 第二個參數: 配置對象,包括 encodingflag,也能夠直接傳如 encoding 字符串
  • 第三個參數: 回調函數

使用方法以下:

const fs = require('fs');
const path = require('path');

fs.readFile(path.join(process.cwd(), 'package.json'), 'utf-8'function (
  error,
  content
{
  if (!error) {
    console.log(content);
  }
});

若是沒傳 encoding,則其默認值爲 null,此時返回的文件內容爲 Buffer 格式。

同步方法

const fs = require('fs');

try {
  fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8');
catch(e) {}

fs.writeFile(file, data[, options], callback)

對應着讀文件 readFilefs 也提供了寫文件的 API writeFile,接收四個參數:

  • 第一個參數: 待寫入的文件路徑
  • 第二個參數: 待寫入的文件內容
  • 第三個參數: 配置對象,包括 encodingflag,也能夠直接傳如 encoding 字符串
  • 第三個參數: 回調函數

使用方法以下:

const fs = require('fs');
const path = require('path');

fs.writeFile(
  path.join(process.cwd(), 'result.js'),
  'console.log("Hello World")',
  function (error, content{
    console.log(error);
  }
);

同步方法

const fs = require('fs');
const path = require('path');

try {
  fs.writeFileSync(
    path.join(process.cwd(), 'result.js'),
    'console.log("Hello World")',
    'utf-8'
  );
catch (e) {}

本文主要是總結了一下在開發 Node 時經常使用的一些 API,後續的文章會帶來 Node 經常使用的一些三方包。

參考資料

[1]

官方文檔: https://nodejs.org/dist/latest-v14.x/docs/api/

[2]

DefinePlugin: https://webpack.js.org/plugins/define-plugin

[3]

https://nodejs.org/dist/latest-v14.x/docs/api/fs.html: https://nodejs.org/dist/latest-v14.x/docs/api/fs.html

交流討論

歡迎關注公衆號「前端試煉」,公衆號平時會分享一些實用或者有意思的東西,發現代碼之美。專一深度和最佳實踐,但願打造一個高質量的公衆號。

❤️ 

公衆號後臺回覆【小煉】

邀請你加入純淨技術交流羣(上班划水摸魚羣)

🙏

若是以爲這篇文章還不錯

來個【分享、點贊、在看】三連吧

讓更多的人也看到

本文分享自微信公衆號 - 前端試煉(code-photo)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索