【问题标题】:asset pipeline giving random version for the same file when asking for a js asset资产管道在请求 js 资产时为同一文件提供随机版本
【发布时间】:2014-09-08 19:17:13
【问题描述】:

我尝试创建一个 Sprocket 指令来考虑我的配置文件中的更改:

initializers/sprockets.rb

class Sprockets::DirectiveProcessor
  def process_depend_on_config_directive(file)
    path = File.expand_path(file, "#{Rails.root}/config/locales")
    context.depend_on(path)
  end
end

application.js

//= depend_on_config en.yml
//= depend_on_config fr.yml

刷新相关 js 文件上的页面给了我不同的答案,我无法修复此行为:

15:02:03 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:03] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 200 23560 0.0105 15:02:05 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:05] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 200 23564 0.0079 15:02:06 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:06] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 304 - 0.0061 15:02:06 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:06]“得到 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 200 23560 0.0091 15:02:07 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:07] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 200 23564 0.0076 15:02:07 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:07] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 304 - 0.0093 15:02:08 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:08]“得到 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 200 23560 0.0080 15:02:08 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:08] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 200 23564 0.0091 15:02:09 web.1 | 127.0.0.1 - - [2014 年 7 月 17 日 15:02:09] “获取 /angular_js/services/better_translate_service-04bd3e149eb227767d3910de31fb2489.js?body=1 HTTP/1.1" 304 - 0.0059

编辑:一些说明:

  • 我想指出的是,资产文件的哈希是相同的,内容是不同的。
  • 当我说刷新页面时,我的意思是我在不同的选项卡中打开资产文件,当我刷新页面时,内容会发生变化。

Edit2:添加更多信息:

更好地翻译服务文件(.erb):

<% environment.context_class.instance_eval { include ApplicationHelper } %>
<%# encoding: utf-8 %>

app.factory('Pg', ['SETTINGS', function(SETTINGS) {
  var polyglot = {};

  polyglot.translations = {

    en: new Polyglot({ phrases: <%=  I18n.with_locale(:en) { phrases_for_polyglot.to_json } %>, locale: "en" }),
    fr: new Polyglot({ phrases: <%=  I18n.with_locale(:fr) { phrases_for_polyglot.to_json } %>, locale: "fr" })
  };

  polyglot.current = 'en';

  polyglot.t = _.memoize(function(key, opts) {
    return polyglot.translations[polyglot.current].t(key, opts);
  }, function(key, opts){
    if(opts===undefined){ return polyglot.current + ''+ key; }
    return polyglot.current + '' + key + polyglot.serialize(opts);
  });


  polyglot.serialize = function(obj) {

    var str = [];
    for(var p in obj){
      if(obj.hasOwnProperty(p)) {
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
      }
    }
    return str.join("&");
  };
  //fde


  polyglot.selectLanguage = function(lang){
    polyglot.current = lang;
  };

  return polyglot;
}]);

开发内容.rb:

# Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports and disable caching.
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise an error on page load if there are pending migrations
  # config.active_record.migration_error = :page_load

  # Debug mode disables concatenation and preprocessing of assets.
  # This option may cause significant delays in view rendering with a large
  # number of complex assets.
  config.assets.debug = true
  config.assets.digest = true

  config.assets.configure do |env|
    env.cache = ActiveSupport::Cache.lookup_store(:null_store)
  end

我正在使用 Rails 4.1.1。有什么建议?我可以根据需要提供更多信息。


尝试答案后更新:我按照以下答案进行了以下更改:

application.js => application.js.erb

<%= depend_on 'en.yml' %>
<%= depend_on 'fr.yml' %>
<% I18n.backend.send(:init_translations) unless I18n.backend.initialized? %>
console.log(<%= I18n.backend.send(:translations).to_json %>);
//= require angular-rails-templates
//= require honeybadger.min
//= require_tree ./dependencies
//= require lodash.min
//= require polyglot.min
//= require lunr.min
//= require angulartics.min
//= require angulartics-ga.min
//= require ./angular_js/fancyinput_library/ac-fancy-input
//= require angular-main
//= require_tree ./angular_js
//= require_tree ../templates

将以下内容添加到 application.rb

config.assets.paths

新发展.rb

# Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports and disable caching.
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise an error on page load if there are pending migrations
  # config.active_record.migration_error = :page_load

  # Debug mode disables concatenation and preprocessing of assets.
  # This option may cause significant delays in view rendering with a large
  # number of complex assets.

  config.assets.compile = true

  config.serve_static_assets = true
  config.assets.debug = false
  config.assets.digest = true

  # config.assets.configure do |env|
  #   env.cache = ActiveSupport::Cache.lookup_store(:null_store)
  # end
  # config.middleware.use Rack::Prerender
  config.root_url = 'lvh.me:5000'
  config.api_host = 'http://lvh.me:3000'

结果:js 错误,应用未加载。

JS 错误:

(anonymous function) MINERR_ASSET:22
(anonymous function) angular.js:3650
q angular.js:303
e angular.js:3616
$b angular.js:3556
Zb.c angular.js:1299
Zb angular.js:1314
Tc angular.js:1263
(anonymous function) angular.js:20555
a angular.js:2342
(anonymous function) angular.js:2613
q angular.js:310
Zc.c angular.js:2612

浏览器中的js文件:

console.log( ... );
//= require angular-rails-templates
//= require honeybadger.min
//= require_tree ./dependencies
//= require lodash.min
//= require polyglot.min
//= require lunr.min
//= require angulartics.min
//= require angulartics-ga.min
//= require ./angular_js/fancyinput_library/ac-fancy-input
//= require angular-main
//= require_tree ./angular_js
//= require_tree ../templates

;

更新 2:我几乎明白了。我注意到我没有在正确的文件中包含 depend_on 方法。我将它们移至相关的 .js.erb 并开始工作。我唯一剩下的问题是我必须刷新页面两次。我认为如果 application.js 无论如何都保持不变会更好。 :)

【问题讨论】:

    标签: ruby-on-rails caching asset-pipeline sprockets


    【解决方案1】:

    这里有几个问题。

    第一:

    我相信您对默认情况下 Rails 如何处理生产中的资产存在误解。

    在生产中,资产将是一次precompiled,仅此而已。回退到生产中的资产管道通常是不明智的,这就是您在 /config/environments/production.rb 中看到这一点的原因:

    # Do not fallback to assets pipeline if a precompiled asset is missed.
    config.assets.compile = false
    

    因此,您的 Sprockets 指令在生产中无法正常工作(默认约定);并且,出于不让您的生产服务器回退到资产管道的充分理由。

    第二:

    您无需编写自己的 DirectiveProcessor 即可完成您想要实现的目标。您需要做的就是将此添加到依赖文件的顶部(即:application.js):

    //= depend_on en.yml
    

    这个给你的/config/application.rb:

    config.assets.paths << Rails.root.join("config", "locales")
    

    Sprocket 将检查该文件是否有更改。

    另外,如果您决定通过编写自己的方法来执行此操作,请将它们注入Environment#context_class,如下所述:https://github.com/sstephenson/sprockets/blob/0d47a4fb459b170f2b2db7386ce7cbf9af1aa590/lib/sprockets/context.rb#L9-L22

    第三:

    您真的不应该在 js.erb 文件中使用 i18n!即使您不关心代码异味,也请考虑不要在生产环境中启用config.assets.compile,因为您会受到很大的性能影响。

    更好的解决方案

    可以在这个答案中找到:Rails: Internationalization of Javascript Strings?

    但是:

    为了完整起见,以下是添加上述更改后正在开发中的示例:

    /config/environments/development.rb

    PartnerUrlApp::Application.configure do
      # Settings specified here will take precedence over those in config/application.rb.
    
      # In the development environment your application's code is reloaded on
      # every request. This slows down response time but is perfect for development
      # since you don't have to restart the web server when you make code changes.
      config.cache_classes = false
    
      # Do not eager load code on boot.
      config.eager_load = false
    
      # Show full error reports and disable caching.
      config.consider_all_requests_local       = true
      config.action_controller.perform_caching = false
    
      # Don't care if the mailer can't send.
      config.action_mailer.raise_delivery_errors = false
    
      # Print deprecation notices to the Rails logger.
      config.active_support.deprecation = :log
    
      # Raise an error on page load if there are pending migrations
      config.active_record.migration_error = :page_load
    
      config.assets.compile = true
    
      config.serve_static_assets = true
    
      config.assets.digest = true
      # Email
      config.action_mailer.default_url_options = { :host => 'localhost:3000' }
    
      # Debug mode disables concatenation and preprocessing of assets.
      # This option may cause significant delays in view rendering with a large
      # number of complex assets.
      config.assets.debug = false
    end
    

    /app/assets/application.js.erb

    <%= depend_on "en.yml" %>
    <% I18n.backend.send(:init_translations) unless I18n.backend.initialized? %>
    console.log(<%= I18n.backend.send(:translations).to_json %>);
    

    /config/locales/en.yml

    en:
      hello: "Hello world"
    

    现在,加载我们的应用程序,我们会在控制台中看到:

    ...
    Started GET "/assets/application-240790de490ac241985d22ea6d94de38.js" for 127.0.0.1 at 2014-07-23 18:45:04 -0500
    ...
    

    然后,修改yaml文件,保存:

    /config/locales/en.yml

    en:
      hello: "DONT DO THIS!"
    

    而且,在不重启服务器的情况下,我们可以看到由于我们的依赖,javascript已经被重新编译:

    ...
    Started GET "/assets/application-ddd20afc0453d275b63d846fee2a5fed.js" for 127.0.0.1 at 2014-07-23 18:45:24 -0500
    ...
    

    【讨论】:

    • 谢谢@Momer,明天我会更详细地查看您的答案,并在我们的应用程序上试用。
    • 在 application.js.erb 中添加这些行破坏了我的应用程序。我得到一个空白页,出现以下错误 Uncaught object MINERR_ASSET:22
    • “Destroyed my application”不能很好地解释这个问题。我使用上面的确切配置来生成我粘贴的结果。你到底改变了什么?而且,堆栈跟踪到底是什么?
    • 问题是我不能再需要其他 js 资产了。我在 .js 文件中得到 // require angular-rails-template ... ,后跟一个 ;在文件末尾。
    • 再一次,“你到底做了什么改变;以及,堆栈跟踪到底是什么?”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 2012-06-08
    • 2012-02-10
    • 2015-09-14
    • 2013-10-12
    • 1970-01-01
    相关资源
    最近更新 更多