NodeJS-JS 轉接器: Webpack


NodeJS 是一款 JavaScript (JS) 的直譯器 (interpreter) 或執行環境 (runtime)。不過 JS 最早是在瀏覽器 (browser) 上執行的,可用來寫網頁應用程式 (web apps),後來才有 NodeJS 可以用來開發獨立運作的應用程式 (standalone apps)。

這兩類 JS 直譯器,browser (pure JS) vs NodeJS,雖然都是基於 JS 語言,但卻有一重大差異:除了語法、一部分核心 APIs 相同,但有些核心 APIs 不相同。例如前者獨有網頁相關的 DOM APIs, 而後者獨有檔案系統讀寫 APIs。之所以會有這些差異,源自於它們一開始的定位不同,一種重於 web apps 開發、另一個重於單機程式開發。除了出發點發展的差異,另一種是本質上的限制造成 APIs 差異,例如 web apps 為了確保其安全,瀏覽器不提供它們直接對使用者裝置的檔案作讀寫,而 NodeJS apps 則沒有這限制。因此在寫 JS 時,知道一個 API 是否支援 browser 還是 NodeJS 是很重要的,用錯是基本行不通的。因此常久以來,兩種 JS 執行環境發展出兩種 JS 程式生態系統。但這種區別是令人沮喪的,因為同一種語言寫的程式,有一部卻無法通用。

幸運的一部分 NodeJS 可利用轉接的方式與 pure JS 作連接。Webpack 就是這麼一套工具,它利用 NodeJS 程式具有模組化的特性 (modules),可以輕易的設定把只相容 NodeJS 的模組替換成相容 pure JS 的模組。例如,fs 是 NodeJS 特定的核心模組,用來存取檔案系統,不可用於 pure JS。而 node-download-helper 套件是基於 fs 開發的一款檔案下載程式,那麼 node-download-helper 是不能直接給 pure JS 使用的。此時我們能用 Webpack 將 node-download-helper 使用的 fs 模組利用別名 (alias) 將其中 fs 指向另一套相容於 pure JS 的 memfs 模組,如此一來 node-download-helper 就能在瀏覽器使用了!

這是什麼魔術,原本不可以用變成可以?以 memfs 來說,它是一款用 pure JS 寫的模組,完全相容 fs 的 APIs,只是差在程式實作的部分很不一樣:瀏覽器環境不支援硬碟檔案系統讀寫,可以用記憶體做檔案系統讀寫, 因此 memfs 是用後者實作。當然 fs 使用的硬碟檔案系統與 memfs 使用的記憶體檔案系統性質不一樣。後者只要一關閉 app,檔案就不見,因此不見得滿足所有人需求。但如果你的 apps 沒此需求(例如可改用 IndexedDB 作儲存的目的),這時這種 NodeJS 轉接 JS 的作法就有意義了:有些 NodeJS 模組/套件不必全用 pure JS 重寫,用 Webpack 轉接後就可以用了!

最後 show 一下最近在 GitHub 的 pull requests 戰績,我在將我的一款 PWA app – 台灣動物認養作套件升級時,發現 memfs 有一 bug:https://github.com/streamich/memfs/pull/842
我的修正被接納、已合併至 master branch😁


Leave a Reply