The asset pipeline

Asset Pipeline 有三個特性:

  • asset directories
  • manifest files
  • preprocessor engines

詳情可以參考這篇:Rails Guides entry on the asset pipeline

Asset directories

在 Rails 3.0 以及之前的版本,Asset 靜態檔案放 public/ 目錄底下:

  • public/stylesheets
  • public/javascripts
  • public/images

這些檔案透過 http://example.com/stylesheets 等網址直接發送給瀏覽器。Rails 3.0 之後的版本也會這麼做。

在最新的 Rails 版本中,Asset 靜態檔案放在三個標準的目錄底下,各有各的用途:

  • app/assets: 給 application 用的檔案
  • lib/assets: 自己開發的檔案
  • vendor/assets: 第三方程式的檔案

這三個目錄底下,還有幾個針對不同類型檔案的子目錄:

$ ls app/assets/
images/ javascripts/ stylesheets/

所以剛剛的 custom.css.sass 放在 app/assets/stylesheets 裡面,因為它只在 application 中使用。

Manifest files

把 Asset 檔案放在適當的目錄底下之後,可以使用 manifest files 告訴 Rails:「嘿!幫我把這些 Asset 檔案合併成一個單一檔案!」(透過 Sprockets gem 實作,只能合併 CSS 和 JavaScript 檔案,圖片無法合併)。

可以看一下 app/assets/stylesheets/application.css

/*
 * This is a manifest file that'll be compiled into application.css, which
 * will include all the files listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets,
 * vendor/assets/stylesheets, or vendor/assets/stylesheets of plugins, if any,
 * can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear
 * at the bottom of the compiled file so the styles you add here take
 * precedence over styles defined in any styles defined in the other CSS/SCSS
 * files in this directory. It is generally better to create a new file per
 * style scope.
 *
 *= require_tree .
 *= require_self
 */

最重要的其實是下面的 CSS 註解,其實是透過 Sprockets 來匯入正確的檔案:

/*
 .
 .
 .
 *= require_tree .
 *= require_self
*/

其中這行:

*= require_tree .

意思是確認在 app/assets/stylesheets 目錄底下的所有 CSS 檔案(包括子目錄的檔案)都會匯入到 application.css

然後這行:

*= require_self

表示會把 application.css 本身有的 CSS 也一起匯入。

Preprocessor engines

準備好 Asset 檔案之後,Rails 會使用 preprocessor engines 來處理檔案,再透過 manifest files 合併檔案,最後發送給瀏覽器。

透過副檔名,可以讓 Rails 知道該用什麼 preprocessor engines 處理檔案。最常用的是:

  • Sass 檔案的 .scss
  • CoffeeScript 檔案的 .coffee
  • ERb 檔案的 .erb

關於 CoffeeScript 可以看這篇文章:RailsCast on CoffeeScript basics

preprocessor engines 可以串接在一起,以下只會使用 CoffeeScript processor:

foobar.js.coffee

這行則會同時使用 CoffeeScript 和 ERb processor:

foobar.js.erb.coffee

preprocessor engines 的副檔名會從右到左處理,所以 CoffeeScript processor 會先被執行。

Efficiency in production

Asset Pipeline 最棒的地方是會自動幫你優化檔案,這樣在正式上線的環境中(production)就可以增進應用程式的效率。以前的方法都是會把 CSS 或 JavaScript 按照功能需求,拆分成好幾個檔案,同時還會使用很多縮排,這對開發者來說很方便,但在 production 中卻降低效益。

當你的檔案很多的時候,反而會加重網頁載入的時間,結果影響使用者的瀏覽體驗。

Asset Pipeline 在 production 環境中,會合併所有 CSS 並匯入到一個 CSS 檔案裡(application.css),也會合併所有 JavaScript 然後匯入到一個 JavaScript 檔案裡(application.js),同時也會壓縮檔案,把空白刪除,降低檔案大小。

這樣就可以在開發環境中使用格式化的檔案,到了正式上線環境使用優化過的檔案。