編寫一個供瀏覽器端使用的NPM包
此文已由作者吳維偉授權網易雲社區發布。
歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。
在編寫程序時,總會有一些代碼是我們不願意一遍又一遍重復地去寫的,比如一些UI或交互相似組件,或是一些相似的流程或邏輯。以前,面對這樣的情況,我會將可以復用的部分抽象出來,做成可以復用的模塊,放在專門存放公用模塊的文件夾中,便於查找和引用。但是這樣只能解決單個項目中公用模塊復用的問題,如果你的模塊需要被多個項目復用,那麽就需要另尋它法了。本文討論的是通過發布npm包來實現模塊復用時有哪些註意事項。
新建一個包
在項目根目錄下執行下面的命令,初始化package.json文件。
$ npm init
文件中各字段的含義可以參考官方文檔。 其中需要註意的是:
name指定包名,在發布包時包名不能與已有包名重復。在發布前可以通過npm info packageName查看包名是否已存在。
main指定加載包時默認加載的文件。
files指定發布包時需要發布的文件。一般來說,.git, node_modules, test等文件不應該發布到npm倉庫中。
dependencies指定需要依賴的第三方包。在安裝此包時,這些第三方包也同時會被安裝。為了提高包的安裝速度,不必要的依賴不要放在dependencies中。
打包
為什麽需要打包
業務項目的打包過程中,為了提高打包速度,某些處理過程會過濾第三方包,如babel。而且業務項目中可能沒有處理第三方庫中某些特性的能力,如第三方包中使用了coffeescript。所以作為一個能被良好復用的第三方包,需要在發布前,對自己的源碼進行編譯打包。
註意事項
可以選擇webpack進行打包。在打包過程中,與業務項目不同的是:
將output.libraryTarget配置為commonjs
業務項目中打包後的文件只需要被執行,並不需要對外導出變量。為了能夠以commonjs規範對外導出變量,需要將output.libraryTarget配置為commonjs點擊查看如何配置
打包時過濾第三方包
作為一個NPM包,可能會依賴一些第三方包,如React。如果直接進行打包,打包後的文件會包含React的代碼。一般依賴這個NPM包的業務項目也會依賴React,所以最終React的代碼會被打包兩次。所以建議在打包時對第三方包進行過濾,並把用到的第三方包聲明在dependencies中,使依賴的第三方包隨業務項目一起打包。
點擊查看如何過濾第三方包
使用babel-plugin-transform-runtime
我們通常會使用babel來編譯代碼。在編譯的過程中,babel會額外註入一些代碼,使編譯後的代碼有更好的兼容性,如繼承,Promise, Map, Set等功能的實現。為了防止這些額外的代碼被重復加入,可以在編譯時使用babel-plugin-transform-runtime插件,使這些額外的功能從第三方包(babel-runtime)中導入,而不是直接添加實現代碼。同時在打包時也要對babel-runtime進行過濾,使babel-runtime隨業務項目一起打包。 點擊查看如何使用transform-runtime
按需加載
有時一個NPM包會提供很多功能,而依賴它的業務項目只需要其中一部分。這個時候,NPM包需要提供按需加載的功能,即在打包時只會將引用的部分模塊打包進來,從而減少打包後文件的體積。
babel-plugin-import的使用
babel-plugin-import插件可以實現按需加載的功能。
{ "plugins": [ ["import", { "libraryName": "abc", "style": true }] ]}
上面的代碼是babel配置文件的一部分,聲明對abc模塊使用按需加載的功能。它對下面的一段代碼進行編譯:
// 從模塊中導入var1, var2, var3 3個變量,只使用了var1import {var1, var2, var3} from ‘abc‘console.log(var1)
編譯結果:
import { style as _style } from ‘abc/lib/var1/style‘;import _default from ‘abc/lib/var1‘; console.log(_default);
編譯前,導入整個abc包。編譯後,只導入了使用了的var1。babel-plugin-import支持更靈活的配置,點擊查看詳情。 點擊查看如何配置babel
為了使babel-plugin-import能夠按需加載我們的NPM包,在打包時需要有一些相應的配置。如上面的abc包,需要對var1, var2, var3等模塊分別打包。所以打包後的文件除了abc/index.js外,還需要有abc/lib/var1/index.js, abc/lib/var1/style.js等
測試
對於一個公用模塊,最重要的應該是它的穩定性。一個每次升級都可能帶來新bug的公用模塊並不是我們想要的。相比於業務項目,公用模塊提供的功能變化較小,這樣單元測試就有了用武之地。想象之中,公用模塊的叠代過程是這樣的:
明確模塊提供的功能,並針對這些功能編寫測試用例。
進行功能開發,通過測試用例。
如果需要修復bug或新增功能,針對bug或新功能編寫測試用例,通過用例。
如何進行單元測試
斷言庫
斷言庫主要用於對數據進行比較,判斷其是否與預期相符。對於不滿足預期的斷言,會拋出一個異常.
assert.equal(‘a‘, ‘b‘)
如上面的斷言會拋出一個異常AssertionError: ‘a‘ == ‘b‘斷言庫推薦使用Chai,支持多種風格的斷言。
測試框架
測試框架可以對測試用例進行分類管理。每一個測試用例在一個單獨的閉包中執行,如果在這個閉包中捕獲到異常,則認為這個測試用例沒有通過。
// 一個分類describe(‘type1:‘, function () { // 一個用例(通過) it(‘case 1:‘, function () { assert.equal(‘a‘, ‘a‘) }) // 一個用例(未通過) it(‘case 2:‘, function () { assert.equal(‘a‘, ‘b‘) }) })
測試框架推薦使用mocha
測試執行器
推薦使用karma,它可以集成webpack、 mocha、 chai、 瀏覽器,對測試代碼進行打包,並在瀏覽器環境下執行測試用例,最後在控制臺輸出結果。
文檔
一個公用模塊應該有一個API文檔,但是手動維護一個文檔的成本過高。所幸現在有一些工具可以根據代碼中的註釋自動生成API文檔,你需要做的只是根據規範添加代碼註釋。 點擊查看註釋規範生成網頁形式的文檔生成markdown形式的文檔
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易技術、產品、運營經驗分享請點擊。
相關文章:
【推薦】 即時通訊推送保障及網絡優化詳解(一)
編寫一個供瀏覽器端使用的NPM包