開發更好用的 JavaScript 模組

發表於2017-12-01

v2-0419ca78b00df4f48dcff73f733514ae_r不少人都曾經在 npm 上釋出過自己開發的 JavaScript 模組,而在使用一些模組的過程中,我經常產生“這個模組很有用,但如果能 xxx 就更好了”的想法。所以,本文將站在模組使用者的角度總結一下,如何能讓模組變得更好用。

提供 ES6 模組的入口

webpack 和 rollup 都支援對 ES6 模組做一些靜態優化(例如 Tree ShakingScope Hoisting),它們都會優先讀取 package.json 中的 module 欄位作為 ES6 模組的入口,若沒有 module 才會讀取 main 欄位作為 CommonJS 模組的入口。通常的做法是:使用 ES6 語法編寫原始碼,然後用模組打包工具結合語法轉換工具生成 CommonJS 模組和 ES6 模組,這樣就可以同時提供 main 和 module 欄位了。

提供 TypeScript 的型別宣告檔案

如果你的使用者使用了 TypeScript 但你的模組沒有提供宣告檔案,他們就不得不在專案中新增一段程式碼避免 TypeScript 的編譯錯誤;另外,這樣做並不只是對使用 TypeScript 的使用者友好,因為大部分程式碼編輯器(Webstorm、VS Code 等)都能識別 TypeScript 的型別宣告,它們可以據此提供更精準的程式碼提示並在使用者傳入錯誤的引數個數或型別時給出提示。

最好的做法是使用 TypeScript 編寫你的模組,編譯時會自動生成型別宣告。除此之外,你也可以參照文件手動維護一份宣告檔案。你可以在你的模組根目錄下新增 index.d.ts 檔案,或者在 package.json 中宣告 typings 欄位提供宣告檔案的位置。

讓模組同時在 Node.js 與瀏覽器中執行

你可以通過檢測是否有名為 window 的全域性變數(例如 !!typeof window)來判斷模組當前是執行在 Node.js 還是瀏覽器中,然後使用不同的方式實現你的功能。

這種方法比較常見,但如果使用者使用了模組打包工具,這樣做會導致 Node.js 與瀏覽器的實現方式都會被包含在最終的輸出檔案中。針對這個問題,開源社群提出了在 package.json 中新增 browser 欄位的提議,目前 webpack 和 rollup 都已經支援這個欄位了。

browser 欄位有兩種使用方式:

  1. 給 browser 欄位提供一個檔案路徑作為在瀏覽器端使用時的模組入口,但需要注意的是,打包工具會優先使用 browser 欄位指定的檔案路徑作為模組入口,所以你的 module 欄位會被忽略,這會導致打包工具不會優化你的程式碼。詳細資訊請參考這個問題
  2. 如果你只想替換其中一些檔案,你可以宣告一個物件。

舉個例子,假設你的模組裡有兩個檔案:http.jsxhr.js,第一個檔案使用 Node.js 中的 http 模組發起請求,另一個使用瀏覽器中的 XMLHTTPRequest 實現了同樣的功能。為了使用適當的檔案,你的模組程式碼中應該始終 require(‘./path/to/http.js’),並在 package.json 中宣告:

這樣一來,當你的模組在打包工具中使用時,打包工具只會將 xhr.js 的程式碼包含在最終的輸出檔案中。

使用各種服務武裝你的專案

大部分 JavaScript 專案都是開源的,而開源社群也提供了很多針對開源專案的免費服務,它們可以給你的專案提供更有力的幫助,這裡列舉幾個比較常用的。

一個專案最常使用的服務就是持續整合了。持續整合服務能將測試、程式碼風格檢測、打包等任務放在伺服器上,並在你提交程式碼時自動執行,常用的有 Travis CICircleCIAppVeyor。Travis CI 對開源專案免費,提供 Linux 與 OS X 執行環境;CircleCI 對開源與私有專案都免費,但每個月有 1500 分鐘的執行時間限制;AppVeyor 提供 Windows 執行環境,同樣對開源專案免費。

執行完測試之後,你還可以將測試覆蓋率上傳到 Coveralls。這個服務能讓你線上瀏覽程式碼的測試覆蓋情況。

如果你想讓你的模組在各個版本的各種瀏覽器、平臺下得到充分的測試,你還可以使用 Sauce LabsBrowserStack,它們都是對開源專案免費的,但需要發郵件申請。

最後,Shields IO 提供了各種圖示,這些圖示能為你的專案提供很多額外資訊,包括但不限於 npm 版本號、下載量、測試通過狀態、測試覆蓋率、檔案大小、依賴是否過期等。


雖然以上的建議大多屬於錦上添花,但這會讓你的模組對使用者更加友好,希望以上的建議能在你開發自己的模組時給你一點幫助。

相關文章