12/08/2018, 09:30

Rails assets pipeline - part 1

Rails Assets Pipeline(RAP) là thuật ngữ quen thuộc với nhiều ROR Developers. RAP được giới thiệu trong Rails 3.1 và được tích hợp vào core cho tới Rails 4.0 thì được tách ra thành một thư viện riêng là Sprockets. Sprockets là một Ruby Gem và được xem như là: “Rack-based asset packaging ...

Rails Assets Pipeline(RAP) là thuật ngữ quen thuộc với nhiều ROR Developers.

RAP được giới thiệu trong Rails 3.1 và được tích hợp vào core cho tới Rails 4.0 thì được tách ra thành một thư viện riêng là Sprockets. Sprockets là một Ruby Gem và được xem như là: “Rack-based asset packaging system”. Ngoài Rails thì Sprockets được sử dụng với một số Rack-based web framework như Sinatra, Padrino, .... Đến bây giờ thì Spockets vẫn được xem như là một phần của Rails.

Trong bài viết này tôi sẽ nghiên cứu sâu hơn về cách hoạt động của RAP trong Rails. Trước khi đọc bài này tôi khuyến khích các bạn đọc chủ đề này ở Rails Guide

Sử dụng command rails assets:precompile để xử lý assets trước khi push lên production. Command này sẽ xử lý assets và lưu chúng vào thư mục public/assets (mặc định) trong ứng dụng rails. Vậy những gì xảy ra bên trong sau khi sử dụng lệnh trên, chúng ta sẽ tìm hiểu trong bài viết này. Bài viết sử dụng rails-4.2.1 và sprockets-3.1.0.

Sprockets::Environment

Theo Sprockets, cần một instance của class Sprockets::Environment để truy vấn và xử lý assets. Instance này đã được định nghĩa sẵn trong rails, sử dụng command Rails.application.assets để thấy config.

image

Có được điều này là vì trong config/application.rb của rails đã require "sprockets/railtie" và code được định nghĩa ở source code github

Load Path

Load Path là danh sách các thư mục assets được sắp xếp theo thứ tự. Ưu điểm của load path là giúp cho Sprockets tìm kiếm assets, dễ dàng kết hợp chúng lại với nhau trong thư viện Ruby. Dưới đây là danh sách các load path đang có trong app của tôi.

/Users/justin/.rvm/gems/ruby-2.1.5/gems/select2-rails-3.5.9.3/vendor/assets/images
/Users/justin/.rvm/gems/ruby-2.1.5/gems/select2-rails-3.5.9.3/vendor/assets/images
/Users/justin/.rvm/gems/ruby-2.1.5/gems/select2-rails-3.5.9.3/vendor/assets/images
/Users/justin/workspaces/rails/crb/app/assets/javascripts
/Users/justin/workspaces/rails/crb/app/assets/stylesheets
/Users/justin/.rvm/gems/ruby-2.1.5/gems/bootstrap-sass-3.2.0.0/assets/fonts
/Users/justin/.rvm/gems/ruby-2.1.5/gems/bootstrap-sass-3.2.0.0/assets/fonts
/Users/justin/.rvm/gems/ruby-2.1.5/gems/bootstrap-sass-3.2.0.0/assets/fonts
/Users/justin/.rvm/gems/ruby-2.1.5/gems/bootstrap-sass-3.2.0.0/assets/fonts

Logical Path

Logical path đường dẫn của assets bên trong load path.

Ví dụ: đường dẫn tuyệt đối của assets là /Users/justin/.rvm/gems/ruby-2.1.5/gems/select2-rails-3.5.9.3/vendor/assets/images/select2.png thì logical path là select2.png còn load path là /Users/justin/.rvm/gems/ruby-2.1.5/gems/select2-rails-3.5.9.3/vendor/assets/images

Dưới đây là danh sách logical path trong ứng dụng của tôi:

select2.png
select2-spinner.gif
select2x2.png
application.js
application.css
bootstrap/glyphicons-halflings-regular.eot
bootstrap/glyphicons-halflings-regular.svg
bootstrap/glyphicons-halflings-regular.ttf
bootstrap/glyphicons-halflings-regular.woff

Tất cả logical path đều nằm bên trong một thư mục gọi là mount point. Đối với Rails thì mount point của Sprockets environment là thư mục assets. Vậy nên khi có yêu cầu từ client file là /assets/application.js thì Sprockets environment sẽ tìm trong tất cả các load path file có tên application.js và trả về cho client. Sprockets environment sử dụng find_asset hoặc [path]để tìm kiếm assets. Ví dụ muốn tìm asset có tên là application.js thì thực hiện truy vấn Rails.application.assets.find_asset "application.js" hoặc Rails.application.assets["application.js"] và kết quả nhận được là:

Bạn có thể tham khảo hàm find_asset ở link

#<Sprockets::Asset:3fd0a8de1724 "file:///Users/justin/workspaces/rails/crb/app/assets/javascripts/application.js?type=application/javascript&id=b0974b418282a4c93731434f474281d7eecb80fdb58a919a9195f9783a1e5bfb">

Bên cạnh đó Sprockets environment còn cung cấp cho chúng ta các hàm để truy vấn tới assets sau khi tìm được. Ví dụ to_s để get content, length để xem độ lớn của content, pathname để get đường dẫn tuyệt đối của asset.

Processors

Assets là js ngoài cách viết là sử dụng javascript thì chúng ta có thể dùng coffee script, css ngoài cách viết thông thường thì còn có thể dùng scss.... Processors là những engine giúp chúng ta convert những định dạng mà client có thể đọc được. Như ở trên thì Processors sẽ convert coffee thành js thường, scss thành css thường.

Chúng ta có thể thấy được nhiều processors trong Sprockets

  • coffee_script_processor
  • erb_processor
  • sass_compressor
  • uglifier_compressor
  • yui_compressor

Compressor

Là những engine sử dụng để nén assets. Chúng ta có thể kiểm tra compressor js và css trong rails bằng

Rails.application.config.assets.js_compressor => :uglifier
Rails.application.config.assets.css_compressor => :sass

Muốn xem các compressors của Sprockets sử dụng Rails.application.assets.compressors

=> {"text/css"=>{:sass=>Sprockets::SassCompressor, :scss=>Sprockets::SassCompressor, :yui=>Sprockets::YUICompressor}, "application/javascript"=>{:closure=>Sprockets::ClosureCompressor, :uglifier=>Sprockets::UglifierCompressor, :uglify=>Sprockets::UglifierCompressor, :yui=>Sprockets::YUICompressor}}

Fingerprinting

Fingerprinting là một kỹ thuật tạo tên của file dựa trên nội dung của file. Điều này có nghĩa là mỗi khi nội dung của file thay đổi thì tên của file cũng sẽ thay đổi theo.

Sprockets sử dụng fingerprinting để chèn một đoạn mã hóa MD5 vào phía sau tên file. Ví dụ: File application.css sau khi sử dụng fingerprinting sẽ có tên là:

application-a39441177e9307e6ac3cd35a66a29f91e33ffc7f72f878d7a45d24f3beac34e8.css

Đoạn mã hóa được thực hiện như sau:

  • Tạo digest dựa trên filepath và lưu vào metadata trong mỗi asset
  • Mã hóa metadata[:digest]

Thông tin mã hóa các bạn tham khảo Sprocket digest_utils Sprocket assets Sprocket base

Manifest Files and Directives

Manifest files hiểu đơn giản là những file chứa assets. Ví dụ application.js là một Manifest file. Manifest chứa các thông tin directives, điều này giúp cho Sprockets xử lý chúng nếu cần, nối thành một file theo thứ tự và cuối cùng là nén lại thành một file css, js. Tất nhiên phải đảm bảo config Rails.application.config.assets.compress true

Như vậy, trên đây tôi đã cố gắng làm rõ hơn những khái niệm trong sprockets. Hiểu được những khái niệm trên sẽ giúp cho bạn dễ dàng tiếp cận part 2 (Quá trình xử lý bên trong). Hẹn gặp các bạn trong phần tiếp theo.

0