一次搞懂 Assets Pipeline

前端之家收集整理的这篇文章主要介绍了一次搞懂 Assets Pipeline前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Assets Pipeline 是 Rails 3.1 一�重要的功能,一直��有很去了解其特性,但因�最近都在�前端的�西在 assets pipeline 的�西上跌跌撞撞了不少次(尤其在 deploy 上 production 後常爆炸,爆到我��自容),�篇就是好好研究後的心得以及��。


Assets Pipeline 有什�好�,不用�怎�?


不用�然不�怎�,你可以在 confing/application.rb 中把他�掉:


1

config.assets.enabled = false

但是 Assets Pipeline 有著�多�良的好�,�助你�理的�去一些需要由第三方元件��理的事情,像是:


�所有的 js 或是 css ��打包成�一�案,�少 http request 的大小��量,增加你�站的效能及速度。

支援像是 SCSS 及 CoffeeScript ��的 high-lever �言,你可以用更��更棒的方式�� css 及 js。

取代原先不可靠的 query string 改用 MD5 的 fingerprint,query string 的用意在於��案�容更�的�候也�一�更��案的 query string,��可以分辨�案是否有更��,因此客�端可以保留快取�比�自己�有的版本以及伺服器上的版本是否一致,�少每次的 request,�奈 query string 的作法�是有些��,像是在部分 CDN 上根本不�快取、在多伺服器的�境中�案名�可能���、以及�多�效的 cache ��,因此在 Rails 3.1 改使用 MD5 的 Fingerprinting �解�了����。

Assets Pipeline 的功能主要由��重要的元件提供:Sprockets 以及 Tilt。Sprockets 用��你的 assets 路�中打包��你所有的 assets 後包�成一��案,然後放到你目的地路�(public/assets),而 Tilt 主要是一��板引擎,用�� Sprockets 可以去解析像是 SCSS、CoffeeScript 或是 ERB 等各��板,你可以�考 Tilt 的 Readme �了解支援哪些�板。


Assets 的��


首先必�了解 Assets 的��,在 Rails 的目���中有三�地方:


app/assets(通常放置我�自己�了自己的程式所�的 js、css 或是 images)

lib/assets(通常是我�所使用的套件中去用到的 assets)

vendor/assets(通常是放一些我���的地方借用的 assets,例如�一些 jQuery 的套件)

�三�目�,在��情�下�三��料�的�西是共通的(因�都�被打包成一��案),你可以把你的 rails app 跑起�後在 http://localhost:3000/assets/application.js 中看到你所有的 js 都在�支�案中,css 同理亦然,你可以在 terminal 中�入 Rails.application.config.assets.paths �查看所有的 assets 路�。你可以��,除了原本我����的三� assets 目�之外,�出�了包含在我� GemFile 中的 jquery,�代表你的 assets �在也可以包成 gem �用,如果你有很多� projects 常重�使用一些共通的 assets,不妨考�包成 gem �使用,方便又愉快。


Assets 的�入


再�是 assets 目�下的�案 import 方式,以 app/asset/javascripts/application.js �支�案�例,�是一支 manifest �案,主要用�告� Sprockets �哪些�案是要被�入最後要被包起���的,最後�支�案�面所有的�西就�被包成 application.js �支�案,也是我� layout/application.html.erb 中的 javascript_include_tag 'application' 中的�案,打��支�案除了上面的�明外只有�三行:


//= require jquery

//= require jquery_ujs

//= require_tree .

上面�行很明�的就是要�入 jquery 以及 jquery_ujs ��支�案,��支�案��有提到他其�是被包含在我�所使用的 Gem 中,而下面那行 require_tree . 表示是把三� assets/javascript 目�下的�案或是子目��的�案全部都包��,��候你一定�想�如果有些 js 或是 css 我只想在某些特定�面中使用的��怎��,例如�假�我�今天有� admin_functions.js 的�案只想在我�的後台使用,有��方法可以使用:


你可以� require_tree 的目�改成其他目�,例如在 app/assets/javascript 目�下建� common �料�,把 require_tree . 改成 require_tree ./common,��子所�生的 application.js �支�案就不�用到 admin_functions.js �支�案。

你可以建立一�新的�料��放你不想要被 application.js �入的�案,例如我�在 app/assets/javascript 下建立一� admin �料�把��的 admin_functions.js �案放�去,然後把原先 application.js 中的 require_tree . 改� require_directory . ��子只�抓� apllication.js �案同目�底下的所有�案而不�去�入子目�中的�案。

最後再建立另外一支 manifest 用� import 那些我�要�立出�的 assets,例如我�建立一支 admin.js 的�案用��入其他功能,一�使用 require_tree 或是 require_directory 的方式��入,然後在你需要用到的�面中使用 javascript_include_tag 'admin' �存取。


千千��要�得,�你使用 application.js 以外的 manifest �案�,一定要在你�境�定�中��支�案加入 precompile 的清�,否�上了 staging 或是 production �你就�收到一堆 500 Error XXXX isn’t precompiled,加入的位置在�境�定�像是 production.rb 中的 config.assets.precompile += %w( search.js ) 中。


除了 require_tree 及 require_directory 之外,�有其他的用法,你都可以使用��或是相�路��指定�案位置,副�名可有可�:


require [路�] �入某支特定�案,如果�支�案被�入多次,Sprockets 也�很�明的只�你�入一次。

include [路�] � require 一�,差�在即使是被�入�的�案也�再被�入。

require_directory [路�] �路�下不包含子目�的�案按照字母�序依次�入。

require_tree [路�] ��路�下包含子目�的�案全部�入。

require_self [路�] 告� Sprockets 再�入其他的�案前,先�自己的�容插入。

depend_on [路�] 宣告依�於某支 js,在需要通知某支快取的 assets �期�非常�用。

stub [路�] �路�中的 assets 加入黑名�,所有其他的 require 都不��他�入。

你可以看 Sprockets 的 Readme ��得更多的��。


Preprocessing


另外就是 Sprockets 在 Tilt 的�助下有 preprocessing 的功能,例如你可以使用像是 something.js.coffee.erb ��的�名,Sprockets ���名的最後面一直解析回去成最後的�案,因此你可以在 js 中使用 CoffeeScript 的�法�� js,�在�面� ruby code ��生你想要的�西,例如:


jQuery ->

number = <%= 1 + 1 %>

不用我�我想你也知道�有什��果。


Helper


Assets 提供了很多路� helper ��你指向你的 assets:


audio_path("horse.wav") # => /audios/horse.wav

audio_tag("sound") # => <audio src="/audios/sound" />

font_path("font.ttf") # => /fonts/font.ttf

image_path("edit.png") # => "/images/edit.png"

image_tag("icon.png") # => <img src="/images/icon.png" alt="Icon" />

video_path("hd.avi") # => /videos/hd.avi

video_tag("trailer.ogg") # => <video src="/videos/trailer.ogg" />

Sass �提供了像是 -url 和 -path ��的 helper ��助你,因此你也可以��使用:



image-url("rails.png") # => url(/assets/rails.png)

image-path("rails.png") # => "/assets/rails.png".

asset-url("rails.png",image) # => url(/assets/rails.png)

asset-path("rails.png",image) # => "/assets/rails.png"

Production


在�不熟悉的情�下,很容易上了 production �境後��原本在本�好好的�西全部炸掉了,因此我�必�了解一下在 production �作�的情形,如果你直接在 console 中打 rails s -e production ��� production �境�,你����上就��� application.css isn't precompiled,�是因�在 production 的�境下我�的 assets 是必�被 compile �後存在 public/assets 底下的,你可以在 console 中打 rake assets:precompile,Rails ��你把所有的 assets �案依照你 manifests 以及�境�定打包��成�一的�案後放在 public/assets 目�底下,所有的�案名���加入 MD5 的 fingerprinting 用�表示其�容供快取,�些 assets �被 Rack Cache middleware 自�的被快取,如果你想要使用自己的 server �取代 middleware 的功能你也可以自己 precompile 後上�。


在你 precompile 後你再打� localhost:3000 �����已��有��,但是�站看起�就是�有 css 的感�,��候查看 log 你�看到 Rails 找不到 assets �案的��,�是因�在 production �境中是不�理���案的,因此你必�先在 production.rb 中� config.serve_static_assets = false 改成 true,��候重�一次就�看到一切正常,我�已��利在本�上跑起 production �境了,你就可以在本�上��你的 assets pipeline 是否正常,如果你去�� precompile 後的�案你���它�都加上了我�之前提到的 MD5 digest,用�辨�其�案�容是否有所更�,因此你可以�你的 Server �定中的 expires ���到最�,因�在�案�有更�的情�下他都�保持相同的�名,�使用者可以�到最快的效能。


Deploy 的小技巧


在本� precompile ��省在 server 上 precompile 的���使用量


一般我�都�使用 Capistrano � Deploy,�得要� Capfile 中的 load 'deploy/assets' 的�解取消,Deploy 的�程中�使用 production server � compile 你的 assets,如果你很在意 production server 的效能,你可以在本�先 compile 後再上�到 Server,我�只需要覆�原本 Capistrano 所提供的 assets:precompile 功能,在你的 deploy.rb 中加入下面的 Code:


namespace:deploydo
namespace:assetsdo
desc"Precompileassetsonlocalmachineanduploadthemtotheserver."
task:precompile,:roles=>web,:except=>{:no_release=>true}do
run_locally"bundleexecrakeassets:precompile"
find_servers_for_task(current_task).eachdo|server|
run_locally"rsync-vr--exclude='.DS_Store'public/assets#{user}@#{server.host}:#{shared_path}/"
end
end
end
end

���在本� precompile 後使用 rsync ��案上�上去,如果你有使用 Git 的��忘了把 public/assets 加到 .gitignore 中。


如果 assets �有更新�,就不要跑 precompile


precompile ��是整� deploy �程中最漫�的一段��,即使你�有更新 assets �也免不了�你跑一下,你可以一�覆� assets:precompile �判�是否有更新 assets,如果�有才�行 precompile:



namespace :deploy do

namespace :assets do

task :precompile,:roles => :web,:except => { :no_release => true } do

from = source.next_revision(current_revision)

if capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l").to_i > 0

run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}

else

logger.info "Skipping asset pre-compilation because there were no asset changes"

end

end

end

end

�然你可以�上面�段 Code 合而�一,有更新 assets 的情�就在本� precompile 後才上�到伺服器:


namespace :deploy do

namespace :assets do

task :precompile,:except => { :no_release => true } do

from = source.next_revision(current_revision)

if capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l").to_i > 0

run_locally "bundle exec rake assets:precompile"

find_servers_for_task(current_task).each do |server|

run_locally "rsync -vr --exclude='.DS_Store' public/assets #{user}@#{server.host}:#{shared_path}/"

end

else

logger.info "Skipping asset pre-compilation because there were no asset changes"

end

end

end

end

�考�料:


RailsGuides Asset Pipeline

Asset Pipeline for Dummies

#279 Understanding the Asset Pipeline

#341 Asset Pipeline in Production

Speed up assets:precompile with Rails 3.1/3.2 Capistrano deployment


转自:http://gogojimmy.net/2012/07/03/understand-assets-pipline/

猜你在找的设计模式相关文章