Rails Asset Pipeline

0. Mở đầu

Chào các bạn, chắc hẳn không ít người đã gặp các lỗi font, thiếu ảnh khi include thư viện bên thứ 3 vào project. Để tìm hiểu nguyên nhân và giải quyết, chúng ta sẽ tìm hiểu về Asset Pipeline

1. Asset Pipeline là gì:

  • Asset Pipeline là 1 giải pháp, nó được implement bởi gem sprockets-rails (Mặc định trong rails), nó giải quyết 1 số vấn đề về assets (JavaScript , CSS,images`).

Asset pipeline cung cấp 1 framework để nối, rút gọn, nén các file JavaScriptCSS trong project.

  • ngoài ra có thể compile các assets trong ngôn ngữ khác (CoffeeScript, Sass, ERB) sang JavaScriptCSS.
  • các assets của gem trong application cũng sẽ được asset pipeline combine lại.

2. Tính năng

a. Nối các assets, các file css riêng biệt thành 1 file, để hạn chế lượng request của browser (Browser giới hạn số lượng request song song, nên nếu ít request sẽ làm ứng dụng load nhanh hơn)

Với cơ chế Fingerprinting những file css, js sẽ được đổi tên khi nội dung bên trong thay đổi, bạn sẽ không cần lo lắng về việc browser cache version cũ của assets dẫn tới các vấn đề ngoài ý muốn

b. Bằng việc xóa bỏ comments, whitespace assets của bạn sẽ được nén lại, tiết kiệm dung lượng và băng thông.

c. hỗ trợ các ngôn ngữ Sass, CoffeeScript, ERB

3. Fingerprinting là gì?

a) Fingerprinting là 1 kỹ thuật, làm cho tết file phụ thuộc vào nội dung của file, khi nội dụng file thay đổi, tên file cũng sẽ được thay đổi (Phù hợp với các nội dung tĩnh, hoặc ít thay đổi như css, js của 1 application), đây là 1 cách để phát hiện ra 2 version của file là giống nhau ngay cả khi các files đó nằm servers khác nhau hoặc ngày deploy khác nhau.

b) Kỹ thuật Sprockets sử dụng là chèn thêm 1 hash vào tên file (ví dụ: global-908e25f4b.css)

4. Cách sử dụng

a. Bạn sẽ viết code trong app/assets, Asset Pipeline sẽ compile chúng vào public/assets trong môi trường staging hoặc production.

b. Cách tổ chức assets.

+ `app/assets` để lưu code bạn custom cho app

+ `lib/assets` để lưu code bạn custom nhưng có thể tái sử dụng được cho app khác

+ `vendor/assets` để lưu code (images, css, js) của bên thứ 3 (các thư viện như bootstrap, font-awesome...) bạn sẽ cần sửa lại code của họ bằng cách sử dụng các helper như asset_path.

c. Search Paths

Khi 1 file được tham chiếu từ manifest hoặc bởi helper, Sprockets sẽ tìm trong 3 thư mục mặc định (mages, javascripts, stylesheets), những file trong thư mục khác cần được chỉ rõ path. Ví dụ:

app/assets/javascripts/home.js
lib/assets/javascripts/moovinator.js
vendor/assets/javascripts/slider.js
vendor/assets/somepackage/phonebox.js

sẽ được tham chiếu bằng cách

//= require home
//= require moovinator
//= require slider
//= require phonebox

Những file ở thư mục khác (sub)

app/assets/javascripts/sub/something.js

sẽ được tham chiếu bằng cách

//= require sub/something

c. Index files

Nếu bạn muốn include 1 thư viện (có nhiều module), chẳng hạn được lưu trong thư mục lib/assets/javascripts/library_name.

File lib/assets/javascripts/library_name/index.js sẽ include tất cả các file js (Có thể theo thứ tự, hoặc require_tree để include tất cả)

Tức là bạn sẽ viết thêm file lib/assets/javascripts/library_name/index.js với nội dung

//= require_tree

Sau đó, Để include vào app viết thêm trong application.js

//= require library_name

d. Truy cập link của assets

Để truy cập link ảnh file "rails.png" trong app/assets/images bạn cần viết trong erb:

<%= image_tag "rails.png" %>

Tương tự nếu có thêm thư mục con icons trong app/assets/images :

<%= image_tag "icons/rails.png" %>

Để truy cập link ảnh trong css bạn cần đổi tên file có định dạng là .scss (application.css.scss) và sửa code :


.class-x {
  background-image: asset-url("rails.png") 
  }

Nếu để nguyên như trong thư viện ngoài (bootstrap,..) bạn sẽ bị lỗi mất ảnh khi lên trên staging hoặc production, vì Asset Pipeline đã đổi tên file "rails.png" sau khi compile.


.class-x {
  background-image: url("../images/rails.png") 
  }

Nếu sử dụng ảnh trong JavaScript/CoffeeScript bạn cần đổi tên file có định dạng là .erb (application.js.erb)


$('#logo').attr({ src: "<%= asset_path('logo.png') %>" });

5. Compile

RAILS_ENV=production bin/rails assets:precompile

Mặc định, chỉ những file có tên (application.js, application.css) mới được compile, nếu muốn include_tag trong views (<%= stylesheet_link_tag 'admin') bạn cần thêm nó vào danh sách compile.

Sửa file config/initializers/assets.rb

Rails.application.config.assets.precompile += %w( admin.js admin.css )

Cách tốt hơn là nên viết code vào assets/stylesheets/admin/application.css.scss , như thế sẽ không cần sửa trong file config.

<%= stylesheet_link_tag  'admin/application'

6. Kết luận

Như vậy những gì bạn cần nhớ là:

  • Các file js hoặc css trong /assets sẽ được Asset Pipeline compile, thành 1 file duy nhất chẳng hạn (application-aee4be71f.js, application-86a292b.css) nhằm mục đích nén, giảm số request của browser để load trang nhanh hơn, bảo đảm version code là mới nhất Cache Invalidation
  • Khi code luôn sử dụng helper (image_tag trong html.erb), (asset-url trong scss)

Tài liệu tham khảo http://guides.rubyonrails.org/asset_pipeline.html

Hi vọng bài viết này hữu ích. ❤️