用于 JavaScript 的 Rails 3.1 资产管道

Posted

技术标签:

【中文标题】用于 JavaScript 的 Rails 3.1 资产管道【英文标题】:Rails 3.1 Asset Pipeline for Javascript 【发布时间】:2011-09-15 22:37:53 【问题描述】:

好的,我已经阅读了很多关于 Rails 3.1 新资产管道的信息,但我找不到正确的答案。

我正在根据我正在渲染的 view#action 按需加载我的 .js 文件。我这样做是为了防止不正确的绑定并加载小的 .js 文件。

candidate_opportunities#index

$(".sortable_drag_n_drop").sortable(
    update: function(event, ui) 
        $.post('/candidate_opportunities/sort', $(this).sortable('serialize'));
    ,
    handle: 'span'
);

candidate_companies#index

$(".sortable_drag_n_drop").sortable(
    update: function(event, ui) 
        $.post('/candidate_companies/sort', $(this).sortable('serialize'));
    ,
    handle: 'span'
);
$(".sortable_drag_n_drop").disableSelection();

现在最好的解决方案是什么?

我是否应该更改我的绑定并让 Sprockets 使用 //= require_tree . 编译我的所有 .js 文件? 或者我应该尝试加载我的 .js 根据我的观点,所以我最终不会有一个巨大的 application.js?

【问题讨论】:

【参考方案1】:

如果您将其更新到管道,您有多种选择。您可能应该在决定时考虑管道的工作方式。

广义上讲,管道的目的是将所有 JS 合并到一个文件中并压缩/压缩它。这样做的目的是减少每页的请求数量,并允许设置远期标头,以便将资源缓存在浏览器或透明代理/缓存中的某个位置。

关于选项。

1.和你现在一样。

你可以继续做你所知道的事情。我假设您正在使用 rails 助手将这些视图 JS 文件添加到主布局文件中。您可以继续对管道执行相同的操作,但是您必须将您使用的所有文件添加到预编译数组中:

config.assets.precompile += ['candidate_opportunities.js', 'candidate_companies']

资产必须在 assets/javascripts 中,但无需将它们添加到清单文件中,因为您正在单独添加每个。

强烈建议您坚持使用 Rails 的默认管道和预编译资产用于生产。

缺点是这些页面上的额外请求,但这仅在应用处于高负载下时才会出现问题。

2。资产管道方式 (TM)

如您所说,要使用管道执行此操作,您需要将这些文件移动到 assets/javascripts 和 require_tree

您的问题是 JS sn-ps 针对同一个类(但使用不同的帖子 URL),所以这不起作用。并且使用 require_tree 文件的顺序可能不是您想要的。

一个新的 3.1 应用程序为视图生成文件(我认为),但期望它们将针对标记中的唯一属性(从站点的角度来看),因为所有文件都包含在 application.js 中

解决 JS 冲突的问题。我建议您重构 JS sn-p 使其更通用。您可以在可排序对象上使用 data-post-url 属性:

<ul class="sortable_drag_n_drop" data-post-url="/candidate_opportunities/sort">

然后在你的 JS 中收集 url。

不仅是 DRYer,而且你的整体 JS 更少,并且可以按预期充分使用管道。

【讨论】:

(2) 正是我会做的。我们不都喜欢数据属性吗? :)【参考方案2】:

我对 Rails 资产管道感到沮丧。也许不是整个资产管道的事情,但 Rails 组织 javascript 的方式确实不合逻辑。

到目前为止,Rails 的每个控制器都有一个单独的 javascript 文件。这在逻辑组织方面有点好。但随后资产管道将所有这些文件压缩成一个大 js 文件。所以基本上你的 js 文件组织得很好,但是它们会一次加载,导致变量冲突、函数冲突、其他代码冲突和其他意外行为。因为作为开发人员,我们真正想要的是一种简单的方式来执行或加载特定于页面的 javascript。

一种著名的方法是每页只包含一个特定的 javascript 文件。是的,这会起作用,但如果我们在每个页面请求不同的 javascript 文件,我们不会使用资产管道提供的性能提升。

我的解决方案是创建一个 javascript 对象,该对象包含所有特定于页面的函数,然后在 Rails 执行匹配的控制器-动作对后获取并执行它们。像这样的:

PageJs = ;
PageJs["users/new"] = function() 
  alert("I will be called when users/new action is executed");
;

基本上,这就是核心思想。好吧,我已经实现了这个想法并为它创建了一个 gem。查看Paloma,了解如何在不进行复杂设置的情况下合理地组织 js 文件并执行特定于页面的 javascript。

这是一个关于如何使用Paloma 的示例:

Javascript 文件:

Paloma.callbacks['users/new'] = function(params)
  // This will only run after executing users/new action
  alert('Hello New Sexy User');
;

Rails 控制器:

def UsersController < ApplicationController
  def new
    @user = User.new
    # No special function to call, 
    # the javascript callback will be executed automatically
  end
end

这只是一个简单的示例,但它提供了更多功能,我相信它可以解决您的问题。很容易。

谢谢!

【讨论】:

以上是关于用于 JavaScript 的 Rails 3.1 资产管道的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3.1 资产管道和手动订购的 Javascript 需要

针对 Rails 3.1+ 的 Jasmine 与 Mocha JavaScript 测试 [关闭]

将 Rails 3.1 项目部署到 Heroku 时出现问题:找不到 JavaScript 运行时

内联 Javascript 在 Rails 3.1 上重新渲染部分 ruby​​ 时无法正常工作

推荐用于 Rails 3.1 和 Ruby 1.9.2 的开发 Web 服务器

Rails 3.1 资产管道:如何加载特定于控制器的脚本?