2013年1月21日

Grails 筆記 - 輕鬆實現 JavaScript 最佳化壓縮與靜態資源 CDN 佈署

在 Grails 2.2+ 使用內建的 Resources Plugin 定義與管理 CSS、JS 資源,建議先將 Grails Resources Plugin 更新到 1.2RC2 或更新。

Grails Resources Plugin
http://grails.org/plugin/resources
runtime ":resources:1.2.RC2"
runtime ":resources:1.2.RC3"

兩個對 Resources 最佳化有幫助的必備 Plugins 分別是 Zipped 與 Cached,分別用來做壓縮與瀏覽器快取,只要安裝好就可以直接用。

Grails Rocks Plugins
http://grailsrocks.com/

Zipped Resources Plugin
http://grails.org/plugin/zipped-resources
runtime ":zipped-resources:1.0"
runtime ":zipped-resources:1.0.1"

如果瀏覽器支援 GZIP 傳輸模式,就啟用壓縮。
Transfer-Encoding header to "gzip"

在官方的 Plugins 說明上使用 1.0 版本,但其實這個 Plugin 已經有 1.0.1,主要是加上 Vary: Accept-Encoding 這個 HTTP-Header,可以讓 Proxy 及 CDN 正確處理經過壓縮的內容。

參考:http://gtmetrix.com/specify-a-vary-accept-encoding-header.html

Cached Resources Plugin
http://grails.org/plugin/cached-resources
runtime ":cached-resources:1.0"
runtime ":cached-resources:1.1"

這個套件會幫每個 .js / .css 進行 SHA-256 編碼,產生 unique 的一組 hash code 取代檔名。如此一來就能告訴瀏覽器該檔案要永久快取,因為內容如果有修改就會使用不同的檔案名。

由於會偵測檔案內容的改變,而使用不同檔名,這對 CDN 的佈署很有幫助,因為 CDN 對靜態資源有 TTL(Time-To-Live)的問題,使用不同檔名剛好是可用的解決方案。

CDN Resources Plugin
http://grails.org/plugin/cdn-resources

目前 Grails 已經不需要搭配 CDN Resources Plugin,所以這邊列出來只是僅供參考;在 CDN Resources 的頁面,有關於 Cloud Front 的設定提示。

實際上新的 Grails Resources Plugin 內建 Resources Mappers "baseurl" 功能,這項設定已經足夠直接用於 CDN 的佈署。

只要在 Config.groovy 的 production 區增加兩行設定。

grails.resources.mappers.baseurl.enabled = true
grails.resources.mappers.baseurl.default = "http://cdn.yourcompany.com/static"

實際將 WAR 佈署到 server 後,就會在所有 static resources(.css / .js)加上 baseurl 的網址。

Google Closure Compiler for Grails Plugins
http://grails.org/plugin/closure-compiler
compile ":closure-compiler:0.9.1"

Closure 是 Google 出品的 JavaScript/CSS Optimizer,功能類似 YUI Compressor 或 Uglify.js 等工具;這邊是用來幫 Grails 的所有 .js 檔案做最佳化,安裝後就可以看到效果。因為 Closure 本來就是 Java-based 的工具,所以使用這個 Grails Plugins 是個不錯的選擇。

簡單說就是網站的 .js 在開發階段,不用自己執行最佳化,Grails 會自動檢查檔案結尾若不是 .min.js,就會幫你跑 Closure Compiler 將 .js 壓縮再輸出。

設定選項有最佳化層級,分成 WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS and ADVANCED_OPTIMIZATIONS.

grails.resources.mappers.googleclosurecompiler.compilation_level='SIMPLE_OPTIMIZATIONS'

但只建議用 SIMPLE_OPTIMIZATIONS,因為 WHITESPACE_ONLY 意義不大,而 ADVANCED_OPTIMIZATIONS 容易產生不能執行的 JavaScript。

設定 defaultBundle

在開發階段為了方便維護,會盡量將 .js 拆成多個檔案,用模組化的概念來寫 code。但是最後必須合併成一個或少數幾個,才能讓網頁載入更快一點。

利用 Grails Resources Plugin 可以輕鬆滿足這項需求。例如在 ApplicationResources.groovy 中加入一個 application 的模組:

     application {
         defaultBundle 'application'

         resource url: 'js/module1.js'
         resource url: 'js/module2.js'
         resource url: 'js/module3.js'
     }

在輸出成 HTML 時,module1-3.js 三個檔案會合併成一個 bundle-application.js 再輸出。當然這個合併的 .js 也會先經過 Cached / Zipped / Closure 的最佳化處理,然後再透過 CDN 佈署。

要實際測試 Grails Web App 最佳化之後的效果,可以利用 Pingdom Tools 這個免費服務。

Pingdom Tools


熟悉這些 Grails Plugins 的安裝與設定方法後,幫一個 Web App 加上相關設定,大約只要幾分鐘就能搞定,網頁載入速度的改善就可以感覺得到。

在 Pingdom 的測試結果中,Load time 從 before 的 8.06s 進步到 after 的 4.40s,平均得分進步 5 個百分點。



依照 Pingdom 給予的建議,再次調整設定,分數又進步五個百分點。


沒有留言:

張貼留言

lyhcode by lyhcode
歡迎轉載,請務必註明出處!