用于 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 时无法正常工作