Categories
通風報信

Use RequireJS Optimizer to deploy Backbone project

此篇範例不適用於RequireJS 2.0,請參考後篇文章

如果有用Backbone在寫網頁的人,應該都會看過有人拿RequireJS來做Asynchronous Module Definition(AMD)把Backbone的Model、View、Cellection還有Router等等都拆開成獨立的Module檔案,這篇文章主要就是要講解如何用RequireJS提供的Optimizer,也就是r.js來壓縮打包這些模組成單一檔案,以便在實際網站上線環境佈署。

首先要先講一下雖然jQuery 1.7之後加入了對AMD的支援,但是Backbone和Underscore卻反而移掉了這個部份,這也讓力推AMD的Dojo FoundationDocumentCloud槓上,另外fork出了支援AMD的版本來維護。如果使用不支援AMD的原版,就必須要對這個問題多加處理,而處理的方法可能各有不同(例如使用RequireJS的order外掛之類的),這裡就直接使用amdjs提供的改進版本來做示範。

一開始先在網頁中使用RequireJS,以及設定引入的第一個檔案:
<script data-main="/javascript/main.js" src="/javascript/require.js"></script>
接著在main.js中設定好相關路徑:


require({
  paths: {
    jquery: 'lib/jquery-1.7.2.min',
    underscore: 'lib/underscore-min',
    backbone: 'lib/backbone-min',
    templates: '../templates'
  },
  priority: ['jquery']
}, [
  'app',
  'lib/jquery.serialize'
  ], function(
    App
  ) {
    App.start();
});

重點是設定priority讓RequireJS先載入jQuery,讓載入後面的jQuery相關外掛時不會出錯。再來是app.js:


define([
  'jquery',
  'underscore',
  'backbone',
  'router'
], function(
  $,
  _,
  Backbone,
  Router
) {
  'use strict';
  var App = {};
  App.start = function() {
    App.router = new Router;
    Backbone.history.start();
  };
  return App;
});

以上大概就是一個標準的Backbone + RequireJS使用樣版。

重頭戲來了,工具先準備好,nodeJSnpm裝好後再:
sudo npm -g install requirejs
安裝好r.js後,在專案底下新增一個build.js來描述處理的相關參數:


{
    baseUrl: 'javascript',
    dir: 'scripts',
    modules: [
      {
        name: 'main'
      }
    ],
    paths: {
      jquery: 'lib/jquery-1.7.2.min',
      underscore: 'lib/underscore-min',
      backbone: 'lib/backbone-min',
      templates: '../templates'
    }
}

baseUrl是要處理的目標路徑,dir則是設定輸出的新增資料夾名稱,得跟前面不一樣以免原始檔案被覆蓋,modules則是要處理的模組檔名,最後但也很重要的是要把paths在這裡也宣告一次。此外如果不想讓它一併處理CSS,可以設optimizeCss: none,更完整的設定項目可以看r.js給的範例

接著一邊大喊「指揮艇,組合!」一邊帥氣地敲下指令:
r.js -o build.js
就可以在設定的輸出資料夾裡看到輸出的成果了。

透過這樣的處理,現在網站只剩require.js和main.js兩個檔案要載入了,那麼有沒有辦法連require.js也一起合併進來呢?是有這樣的作法,不過requireJS的檔案壓縮後只剩10幾Kb,如果要再精打細算,可以用較輕巧的almond.js來合併,將下載的almond.js重新命名為script.js然後擺在原本未處理前的main.js旁邊,再修改剛剛的build.js,在modules的部份:


modules: [
      {
        name: "script",
        include: ['main']
      }
    ],

這個新的鍊成陣使用include設定讓script.js同時引入main的內容再做最佳化處理。這樣在網頁的部份就只要載入一份最佳化後的script.js就可以了:
<script src="script.js"></script>

使用almond代替require有一些使用上的限制,畢竟壓縮後不到2Kb,有不少RequireJS的功能無法支援,可以看Github專案頁面的說明,例如它就無法處理A模組定義引用B模組,同時B模組也定義引用A模組的情況,不過會寫成這樣,應該要先檢討專案的架構跟寫法才是。

要是遇上真的無法使用almond代替的場合,是不能把require.js丟進去用的,因為r.js會自動略過requireJS不處理,這樣只能把自己把壓縮後的require.js串接到壓縮後的main.js前面了。

延伸閱讀:
Module, AMD, RequireJS
初探 Require.JS
利用 RequireJs 將 Backbone.js 程式模組化

One reply on “Use RequireJS Optimizer to deploy Backbone project”

發表迴響