Browserify: 取代 RequireJS ?

此篇文章最近更新時間為2014-05-09 21:04:53 目前共有2篇留言

關於作者 - JosephJ

任職於 Faria。喜好戶外運動、2008 年 5 月完成「跑步環島」。對於新技術跟程式碼有著強烈的偏執狂。

如果網站有一定規模、必定得用像是 RequireJS 或 YUI 這類可以將 JavaScript 切分模組及定義相依性(Dependencies)的工具。除了可達成程式語言本來就應該顧及的 Seperate of Concern 外,也可避免瀏覽器端也很容易碰到 JavaScript 檔案的前後順序衝突、重複載入(當前頁面用不到)、載入效能(一大包而非非同步)、不易維護(不敢移除)等等的問題。

RequireJS 已出局?

先前工作也是用 RequireJS,一直認為這是 Open Source 界中做模組化最好的工具(其實 YUI Module + Loader 考慮更多面向,但是比較不受歡迎 :p)但昨天看到斗大的標題「Grunt 與 RequireJS 出局、現在是 Gulp 與 Browserify 的天下」( Grunt and RequireJS are out, it's all about Gulp and Browserify now ) Grunt 被 Gulp 取代較不意外、但 RequireJS 會被取代就挺驚訝的,趕緊來看看 Browserify 的相關文章。我個人覺得最值得一讀的是 Journey From RequireJS to Browserify (不過也是一年前的舊聞了 XD)

RequireJS 的問題

若沒有考慮到 build 的最佳化(r.js),RequireJS 本身只是一個 Client 端的 JavaScript Library,在開發階段會以非同步的方式載入一個個相依性的模組 JavaScript 檔案,除錯簡單又容易理解。但最大的問題就是只支援 AMD 格式的模組檔(當初有雄心壯志的願景一統 JS 模組的格式,但還是許多受歡迎的函式庫不支援),衍生出許多得組態設定 Shim、甚至得自己 fork 一份下來改成相容格式等問題。若牽扯到最佳化的 r.js 又是更複雜的議題... 得額外設定、也無法避免與開發環境有所不同

Browserify 的運行原理

第一眼看到 Browserify 並不太吸引人,因為只要有修改都得做 compile:

$ browserify --debug index.js > bundle.js

這個指令就是把 index.js 中、有用 require() 載入的所有模組檔與 index.js 本身打成一包成為 bundle.js。而 --debug 則是產生 SourceMap 讓開發者好除錯,不然開發階段就一大包是不好找到原始檔案所在行數。

var uniq = require('unique'),
    querystring = require('querystring'),
    a = require('./a'),
    b = require('./b');      

index.js 中引用了 Node.JS 內建的 unique, querystring 與自己寫的 a.js, b.js,經過 browserify 處理後會變成一大包 bundle.js

其實 Browserify 只是遵守 CommonJS 的規範用 module.export 與 require() 達成模組化相依性控管的工具。而純瀏覽器端是無法達成的、得依賴這個 browserify 的指令做 compile 才行。

做什麼都得 compile 似乎已經是當前網站開發的主流:例如 Coffee、Sass、HAML 都一樣,所以倒沒有特別排斥,只要使用 GruntJS 或 gulp.js 之類的工具來處理即可。官網也推薦了 watchifybeefy 方便 Browserify 開發的工具。

Browserify 的好處

Browserify 很重要的好處:從命名本身就可以看得出來將 Node.JS 或 npm 的模組可以「瀏覽器化」統一使用。加上 CommonJS 的模組規範與 npm 套件是 Node.JS 的基礎標準,這也表示你寫的JavaScript 模組真的可以在前後端重複使用、還能夠放到 npm 中。(有人會寫個 Universal Header 讓模組可以相容在 CommonJS, AMD, 與一般瀏覽器,略嫌麻煩些)。優點列表簡單整理如下:

  • 設定單純、語法簡單,會 Node.JS 就會 Browserify
  • Shim 比較直覺
  • 套件比 RequireJS (因為是 npm)
  • 支援 SourceMap、支援 CoffeeScript(這好像也是很基本的事情)
  • Node.JS 內建的模組例如 events, stream, path, url, buffer, util, querystring, http... 都可以使用
  • 開發環境與佈署環境一致(因為全部都壓成一個 bundle)

Browserify 的壞處

RequireJS 的好處就是非同步載入,即使在非開發環境也可以透過設定做到。但 Browserify 基本上就是打包工具,一不小心可能會製作出非常大一包、使用者得花一段時間下載才能開始用。因此 Browserify 較適合小型專案使用。如果要用在大型專案上,就得考慮配合其他的 Script Loader 例如 LABjs、yepnope.js、Head.js 來達成,有大型專案需求可參考此篇文章:Asynchronous Module Loading With Browserify

  • 不適合直接用在大型專案、得整合其他非同步的函式庫。
  • 難以在舊的瀏覽器做 Debug:因為不支援 SourceMap。
  • 非純前端函式庫:需要伺服器端支援,隨時監控並重新編譯 bundle。

此外有人會覺得把純瀏覽器端的 JavaScript 放在 npm 並不是一件好事,應該要放在像是 bower 這樣的前端套件管理比較適合。但看起來比較多人不是這樣想的、而我也比較傾向可以把純前端套件放到 npm:畢竟套件就是一包,看開發者自行決定怎麼用,分太多種 Package Management System 反而不易管理。

結論

我認為 Browserify 用起來比較直覺、整合 npm 後,能用的資源感覺更多了、而效能問題本來就得另外處理(RequireJS 也得花時間組態設定及測試)。整體來說,我是覺得值得採用的。但以上只是讀書心得,還是要找個小專案來實際試用看看才比較有感覺。另外比起跑個 watcher 做監控,我是比較喜歡 middleware 的方式,可能會在 Express 上使用 browserify-middleware 來達成。

官方網站:http://browserify.org/



Comments

  1. 寸志 2014-08-26 00:56:17
    可以试试:https://github.com/island205/browserify-loader
  2. Tim 2014-05-31 05:28:19
    No colmapints on this end, simply a good piece.
暱稱: 必填。
Email: 非必填。若填寫為不公開欄位,僅供站長參考聯繫。
內容: 必填。限 255 個字元以內。
驗證碼:
送出

Facebook Comment