Asset Pipeline
什麼是 Asset Pipeline
這次 Rails 3.1 提供的 Asset Pipeline 是一套讓開發者很方便能夠削減 (minify) 以及 壓縮 (compress) Javascript / CSS 檔案的框架。它同時也提供你直接利用其他語言如 CoffeeScript / SASS / ERB ,直接撰寫這些 assets (註1) 的可能性。
[註1] : assets 指的是 stylesheets / javascripts / images 這些靜態檔案。
提昇前端速度的優勢
一般在做前端提速時,我們通常會依據 Yahoo 提供的 Best Practices for Speeding Up Your Web Site 這篇文章提及的一些技巧對網站優化,諸如:
- Minimize HTTP Requests
- Use a CDN
- Split Components Across Domains
- Gzip Components
- Minify JavaScript and CSS
- CSS Sprites
在 3.1 之前,能夠使用 Rails 內建機制達成的只有這三項:
- Minimize HTTP Requests
使用
1 2 | |
將數支檔案打包成一支,降低 HTTP requests。
- Use a CDN + Split Components Across Domains
租用 CDN,再使用
1
| |
使網站的靜態檔案從以下網址
- http://cdn0.example.org
- http://cdn1.example.org
- http://cdn2.example.org
- http://cdn3.example.org
平均動態提供,達到網頁高速載入的效果。
原有內建機制不敷實際使用
雖然已內建這些機制,但是對於一般有較大吞吐量的網站,還是不敷使用。
原因 1: 不只打包,更需壓縮
現在的網站設計師,多半會使用一些現成的 CSS 框架( 如 960 / Blueprint …etc.) 來做快速 prototyping。而網站逐漸擴充功能,一個網站的靜態檔案數量與所佔容量也會隨著水漲船高。有時候光 CSS 與 Javascripts 的檔案,加起來就足足有 1MB 以上的 size。
Rails 原先內建的功能,充其量只有將這些檔案「打包」,並沒有將檔案「壓縮」的作用。
若要談加速下載,唯有進行「壓縮」才能達到真正減肥提升速度的目標。
壓縮:trim / uglify / gzip
字面上的「壓縮」其實還分幾種作法:
- 把不要的空白 / 不必要的注釋 去掉 (trim)
- 把檔案的變數以單個字母取代 ( uglify )
- 將檔案壓成 gz
市面上有幾套工具提供 ( trim / uglify ) 這樣的功能:如 YUI Compressor / Google Closure Tools。
原因2: 主流 CDN 不一定支援 assets query string
Rails 原先的 assets helper 內建 query string,來達到 invalid browser cache 的作用。如:
1
| |
會生成
1
| |
query string 數字的演算法,是根據該 assets 更新的時間去定義。
這樣每次 deploy 網站時,可以保證: assets 只要被更動過,query string 都會不一樣,而 browser 就將之視為不同的 URI,重新下載。
不過相當不幸運的,不是每一家 CDN 都支援 query string,如非常有名的 CDN : Amazon Cloudfront,就不支援 query string 的設計。
再者,stylesheets 內的 images,並不在 query string 的 cover 範圍,也就是如果你使用了
1
| |
當你替換了 CSS 內的背景圖原始圖檔,或者是 CDN 不支援 query string。通常每 deploy 一次,你就必須上 CDN panel 去手動 invalid assets,並沒有辦法讓使用者的 browser 自動清除。
使用 3rd Party Tool : Jammit 解決部份問題
以上所談這些 issue,其實都有各自的獨立解決工具。但是若真要組合到 Rails deployment process 中,就需要很大的工夫另行打造。因此就有開發者開發出了一套十分 powerful 的 assets packaging 工具:Jammit。
Jammit 提供了絕大部分上述之需求之解決方案:
- 打包
- 壓縮 ( compress / uglify / gzip )
- background image query string
等等…
除了無痛整合進 Rails 之外,也提供了 Capistrano Recipe 可直接整合在 deployment process 中。
「Fast by default」strategy
「Fast by default」 strategy ,Rails 之父 DHH 在 2011 Rails Conf Keynote 喊出這樣的口號。
Rails 既然是套「框架」,以上 Jammit 實作的解法。是否能在 Rails Framework 中直接提供,作為內建 feature 呢?
能!
這也就是這次 Assets Pipeline 關於提速部分被開發的主要原因。Rails 3.1 使用了 Sprocket 這套 gem 作為核心實際 assets packing 的引擎。
Sprockets 提供了絕大部分 Jammit 實作出來的主要 feature,更增加了 fingerprinting assets 以及直接支援 SASS / CoffeeScript / ERB 寫作 Assets 的功能(此部份會在其他章節提及)。
Fingerprinting Assets and Why should you care?
在上面 CDN 的章節我們提過,query string 不算是一個好的解法。因為 CDN 不一定支援。
那有沒有其他的 auto invalid 解法呢?
有!
既然不能在 query string 上動手腳。那就直接在檔名動手腳!
Sprockets 提供的 fingerprinting assets 提供了另外一套解決途徑。將實際會使用到的 assets 算出 MD5 checksum,再壓出一份帶有 hash 的檔名去 serve,這樣就解了原有的問題了。
小結
相信看到這裡,你應該對 Asset Pipeline 的野心有了初步的了解。但這並非 Asset Pipeline 全部的藍圖。
眼尖的你,應該也會發現到,其實我漏了幾條提速 Rule 沒有解說。別擔心,這部份的內容我將會在下一章「SASS」繼續補充。
我們下回見!
補充資料:
官方 Asset Pipeline 文件 http://guides.rubyonrails.org/asset_pipeline.html