Node.js Web Streams API:與瀏覽器同步的現代串流標準

在 Node.js 的歷史中,我們一直使用 node:stream 模組來處理資料流。雖然它非常強大,但它是 Node.js 特有的,不符合瀏覽器端的 Web 標準。

Node.js 18 開始,Node.js 內建支援了與瀏覽器完全一致的 Web Streams API (ReadableStream, WritableStream, TransformStream)。這讓你寫出來的串流處理程式碼能無縫地運行在瀏覽器、Node.js 與 Edge 運算環境(如 Cloudflare Workers)中。

認識 Web Streams API

與 Node.js 原生串流相比,Web Streams 的介面更現代化,並且深度整合了 async/await

  • ReadableStream:資料的來源,支援非同步疊代 (Async Iteration)。
  • WritableStream:資料的去處,支援背壓 (Backpressure) 管理。
  • TransformStream:在傳輸過程中對資料進行轉換。

實戰開發:使用 Web Streams 處理 HTTP 請求

Node.js 的 fetch API 底層就是使用 Web Streams。

1. 建立一個簡單的讀取流

const { ReadableStream } = require('node:stream/web');

const readable = new ReadableStream({
  start(controller) {
    controller.enqueue('Hello ');
    controller.enqueue('Web ');
    controller.enqueue('Streams!');
    controller.close();
  },
});

// 使用 for-await 讀取
(async () => {
  for await (const chunk of readable) {
    console.log('收到:', chunk);
  }
})();

2. 在 HTTP Server 中使用 Web Streams

雖然原生的 http 模組使用的是 Node.js 傳統串流,但我們可以輕鬆地進行轉換:

const { Readable } = require('node:stream');
const http = require('http');

http
  .createServer(async (req, res) => {
    // 將 Node.js 傳統串流轉為 Web ReadableStream
    const webStream = Readable.toWeb(req);

    const reader = webStream.getReader();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      console.log('讀取到 Chunk 長度:', value.length);
    }

    res.end('處理完畢');
  })
  .listen(3000);

實用的資料轉換:TransformStream

假設我們想要一個能自動將所有英文轉為大寫的串流:

const { TransformStream } = require('node:stream/web');

const upperCaseTransform = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(chunk.toString().toUpperCase());
  },
});

// 使用 pipeThrough 進行流水線作業
// sourceStream.pipeThrough(upperCaseTransform).pipeTo(destStream);

Node.js 串流與 Web 串流:該選哪一個?

特性Node.js 原生串流 (Legacy)Web Streams API (Modern)
通用性僅限 Node.js / Electron跨平台 (Browser, Node, Deno, Bun)
主要方法pipe()pipeTo(), pipeThrough()
背壓控制基於事件發送與 drain內建於 API 底層,更自動化
發展趨勢依然穩定,主要用於存取 OS 資源未來各種 Fetch/Web API 的標準

什麼時候該轉向 Web Streams?

  • 推薦:開發開源套件(需跨環境支援)、使用 Fetch API 處理大型檔案下載、或是追求更現代的非同步程式設計風格時。
  • 沿用傳統:處理磁碟檔案 (fs.createReadStream)、或是目前現存於 Node.js 核心大部分的 API 呼叫。

總結

  1. Web Streams 是未來的跨平台標準。
  2. 內建 pipeThrough 機制讓資料處理像樂高積木一樣好組裝。
  3. 掌握 Web Streams 能讓你的 Node.js 技術棧更具備「雲端原生」與「跨端開發」的優勢。