[譯] 同中有異的 Webpack 與 Rollup

lsvih發表於2017-04-12

同中有異的 Webpack 與 Rollup

[譯] 同中有異的 Webpack 與 Rollup

本週,Facebook 將一個非常大的 pull request 合併到了 React 主分支。這個 PR 將 React 當前使用的構建工具替換成了 Rollup。這讓許多人感到不解,紛紛在推特上提問:“為什麼你們選擇 Rollup 而不選擇 Webpack 呢?”1 2 3

有人問這個問題是很正常的。Webpack 是現在 JavaScript 社群中最偉大的成功傳奇之一,它有著數百萬/月的下載量,驅動了成千上萬的網站與應用。它有著巨大的生態系統、眾多的貢獻者,並且它與一般的社群開源專案不同——它有著意義非凡的經濟支援

相比之下,Rollup 是那麼的微不足道。但是,除了 React 之外,Vue、Ember、Preact、D3、Three.js、Moment 等眾多知名專案都使用了 Rollup。為什麼會這樣呢?為什麼這些專案不使用大家一致認可的 JavaScript 模組打包工具呢?

這兩個打包工具的優缺點

Webpack 由 Tobias Koppers 在 2012 年建立,用於解決當時的工具不能處理的問題:構建複雜的單頁應用(SPA)。尤其是它的兩個特點改變了一切:

  1. 程式碼分割可以將你的 app 分割成許多個容易管理的分塊,這些分塊能夠在使用者使用你的 app 時按需載入。這意味著你的使用者可以有更快的互動體驗。因為訪問那些沒有使用程式碼分割的應用時,必須要等待整個應用都被下載並解析完成。當然,你也可以自己手動去進行程式碼分割,但是……總之,祝你好運。
  2. 靜態資源的匯入:圖片、CSS 等靜態資源可以直接匯入到你的 app 中,就和其它的模組、節點一樣能夠進行依賴管理。因此,我們再也不用小心翼翼地將各個靜態檔案放在特定的資料夾中,然後再去用指令碼給檔案 URL 加上雜湊串了。Webpack 已經幫你完成了這一切。

而 Rollup 的開發理念則不同:它利用 ES2015 模組的巧妙設計,儘可能高效地構建精簡且易分發的 JavaScript 庫。而其它的模組打包器(包括 Webpack在內)都是通過將模組分別封裝進函式中,然將這些函式通過能在瀏覽器中實現的 require 方法打包,最後依次處理這些函式。在你需要實現按需載入的時候,這種做法非常的方便,但是這樣做引入了很多無關程式碼,比較浪費資源。當你有很多模組要打包的時候,這種情況會變得更糟糕

ES2015 模組則啟用了一種不同的實現方法,Rollup 用的也就是這種方法。所有程式碼都將被放置在同一個地方,並且會在一起進行處理。因此得到的最終程式碼相較而言會更加的精簡,執行起來自然也就更快。你可以點選這兒親自試試 Rollup 互動式直譯器(REPL)

但這兒也存在一些需要權衡的點:程式碼分割是一個很棘手的問題,而 Rollup 並不能做到這一點。同樣的,Rollup 也不支援模組熱替換(HMR)。而且對於打算使用 Rollup 的人來說,還有一個最大的痛點:它通過外掛處理大多數 CommonJS 檔案的時候,一些程式碼將無法被翻譯為 ES2015。而與之相反,你可以把這一切的事全部放心交給 Webpack 去處理。

那麼我到底應該選用哪一個呢?

到目前為止,我們已經清晰地瞭解了這兩個工具共存並且相互支撐的原因 — 它們應用於不同的場景。那麼,現在這個問題的答案簡單來說就是:

在開發應用時使用 Webpack,開發庫時使用 Rollup

當然這不是什麼嚴格的規定——有很多的網站和 app 一樣是使用 Rollup 構建的,同時也有很多的庫使用 Webpack。不過,這是個很值得參考的經驗之談。

如果你需要進行程式碼分割,或者你有很多的靜態資源,再或者你做的東西深度依賴 CommonJS,毫無疑問 Webpack 是你的最佳選擇。如果你的程式碼基於 ES2015 模組編寫,並且你做的東西是準備給他人使用的,你或許可以考慮使用 Rollup。

對於包作者的建議:請使用 pkg.module

在很長一段時間裡,使用 JavaScript 庫是一件有點風險的事,因為這意味著你必須和庫的作者在模組系統上的意見保持一致。如果你使用 Browserify 而他更喜歡 AMD,你就不得不在 build 之前先強行將兩者粘起來。通用模組定義(UMD)格式對這個問題進行了 部分 的修復,但是它沒有強制要求在任何場景下都使用它,因此你無法預料你將會遇到什麼坑。

ES2015 改變了這一切,因為 importexport 就是語言規範本身的一部分。在未來,不再會有現在這種模稜兩可的情況,所有東西都將更加無縫地配合工作。不幸的是,由於大多數瀏覽器和 Node 還不支援 importexport,我們仍然需要依靠 UMD 規範(如果你只寫 Node 的話也可以用 CommonJS)。

現在給你的庫的 package.json 檔案增加一個 "module": "dist/my-library.es.js" 入口,可以讓你的庫同時支援 UMD 與 ES2015。這很重要,因為 Webpack 和 Rollup 都使用了 pkg.module 來儘可能的生成效率更高的程式碼——在一些情況下,它們都能使用 tree-shake 來精簡掉你的庫中未使用的部分。

瞭解更多有關 pkg.module 的內容請訪問 Rollup wiki

希望這篇文章能讓你理清這兩個開源專案之間的關係。如果你還有問題,可以在推特聯絡rich_harrisrollupjsthelarkinn。祝你打包快樂!

感謝 Rich Harris 寫了這篇文章。我們堅信開源協作是共同促進 web 技術前進的重要動力。

沒有時間為開源專案做貢獻?想要以其它方式回饋嗎?歡迎通過 Open Collective 進行捐贈,成為 Webpack 的支持者或贊助商。Open Collective 不僅會資助核心團隊,而且還會資助那些貢獻出空閒時間幫助我們改進專案的貢獻者們。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃

相關文章