2011-09-24 126 views
25

命令「rake assets:precompile」對我來說工作非常緩慢。特別是在我的Amazon EC2 Micro生產服務器上,它沒有很多處理器資源。在EC2上,我必須在每次部署期間等待1分鐘或更長時間,僅用於此預編譯任務。有沒有辦法讓它更快?rake資產:預編譯速度慢

以前我用Jammit來壓縮/縮小css和js。 Jammit在同一個網站和服務器上的工作速度快了近10倍。

+2

你可以在部署之前預編譯你的資產 –

+1

對,我想過這個。但我不知道如何輕鬆地將預編譯資產部署到生產環境。我正在使用capistrano,每次它都會將預編譯的資產提交給git。我擔心的是,在這種情況下,git存儲庫將會快速增長,並保留以前所有資產的歷史記錄。這不僅僅是css/js - 而且還包括所有的資產圖片。 – Evgenii

+2

對我來說也是非常慢(135,987ms = ~2分鐘)。在部署之前,我將不得不考慮預編譯......我也很關心將它們添加到git中,主要是因爲這會給git日誌添加很多噪音。我建議不要將它們添加到git中 - 只需從本地主機將rsync目錄作爲cap部署腳本的一部分添加到Web服務器。 –

回答

30

如果您不需要加載Rails環境,你應該禁用與:

config.assets.initialize_on_precompile = false 

編輯:我剛寫了一個寶石來解決這個問題,叫turbo-sprockets-rails3。它僅通過重新編譯更改的文件來加速您的assets:precompile,並且只編譯一次即可生成所有資產。

如果你能幫我測試一下turbo-sprockets-rails3寶石,並且讓我知道你是否有任何問題,那將會非常棒。

+3

你的寶石非常棒。用d3解決了我的問題,並進行了預編譯。謝啦 – chaostheory

10

有一個bug in Rails 3.1.0在預編譯過程中包含太多的文件。如果你有許多資產js和css資產,這可能是緩慢的原因。

另一個是Sprockets(編譯gem)更復雜,必須考慮更多選項 - scss,coffeescript和erb。正因爲如此,我懷疑它只會串聯和縮小而變慢。

如上所述,如果仍存在問題,您可以在部署文件之前進行預編譯。

+0

謝謝你的解釋。我也認爲它很慢,因爲它需要在生產環境中加載rails環境,而Jammit並不是這種情況。無論如何,我不會回到Jammit。我很喜歡資產管道。 – Evgenii

1

我的解決方案是從預編譯中排除application.js .css和任何其他應用程序相關資產。因此,我只能使用rake assets:precompile一次僅預編譯引擎相關資產。

然後在每個部署我用一個簡單的rake任務來構建的任何應用程序相關的資產,並把它們合併成manifest.yml

namespace :assets do 
    task :precompile_application_only => :environment do 
    require 'sprockets' 

    # workaround used also by native assets:precompile:all to load sprockets hooks 
    _ = ActionView::Base 

    # ============================================== 
    # = Read configuration from Rails/assets.yml = 
    # ============================================== 

    env   = Rails.application.assets 
    target  = File.join(::Rails.public_path, Rails.application.config.assets.prefix) 
    assets  = YAML.load_file(Rails.root.join('config', 'assets.yml')) 
    manifest_path = Rails.root.join(target, 'manifest.yml') 
    digest  = !!Rails.application.config.assets.digest 
    manifest  = digest 


    # ======================= 
    # = Old manifest backup = 
    # ======================= 

    manifest_old = File.exists?(manifest_path) ? YAML.load_file(manifest_path) : {} 

    # ================== 
    # = Compile assets = 
    # ================== 

    compiler = Sprockets::StaticCompiler.new(env, 
              target, 
              assets, 
              :digest => digest, 
              :manifest => manifest) 
    compiler.compile 

    # =================================== 
    # = Merge new manifest into old one = 
    # =================================== 

    manifest_new = File.exists?(manifest_path) ? YAML.load_file(manifest_path) : {} 

    File.open(manifest_path, 'w') do |out| 
     YAML.dump(manifest_old.merge(manifest_new), out) 
    end 

    end 
end 

要指定編譯的資產,我使用一個YAML配置文件(config/assets.yml):

例如。

--- 
- site/site.css 
- admin/admin.css 
- site/site.js 
- admin/admin.js