简体   繁体   English

Rails 3.1 Asset Pipeline for Javascript

[英]Rails 3.1 Asset Pipeline for Javascript

Ok, I've read a lot of information about the new Asset Pipeline for Rails 3.1 and I couldn't find a proper answer to my doubt. 好的,我已经阅读了很多有关新的Rails 3.1 Asset Pipeline的信息,但找不到我的疑问的正确答案。

I was loading my .js files according to the view#action I was rendering, on demand. 我正在根据需要渲染的view#action加载.js文件。 I was doing this to prevent incorrect bindings and to load small .js files. 我这样做是为了防止错误的绑定并加载小的.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();

What is the best solution now? 现在最好的解决方案是什么?

  • Should I change my bindings and let Sprockets compile all my .js files using //= require_tree . 我应该更改绑定并让Sprockets使用//= require_tree .编译所有.js文件//= require_tree . ?
  • Or should I try to load my .js according to my views, so I don't end up with a huge application.js ? 还是我应该根据自己的观点尝试加载.js ,因此我不会以庞大的application.js结尾?

If you are updating this to the pipeline you have several options. 如果要将其更新到管道中,则有几种选择。 You should probably take the way the pipeline should work into account in deciding. 在决定时,您可能应该考虑管道应起作用的方式。

Broadly speaking, the aim of he pipeline is to join all your JS into one file and minfy/compress it. 广义上讲,管道的目的是将您所有的JS合并到一个文件中,并将其压缩/压缩。 The point in doing this is reduce the number of requests per page, and to allow far-future headers to be set so that the resource is cached at the browser or somewhere in a transparent proxy/cache. 这样做的目的是减少每页的请求数量,并允许设置远期头,以便将资源缓存在浏览器或透明代理/缓存中的某个位置。

On to the options. 转到选项。

1. The same as you do now. 1.与您现在相同。

You could keep doing the same thing as you do know. 您可以继续做自己知道的事情。 I presume that you are using the rails helpers to add these view JS files in the main layout file. 我假设您正在使用rails助手在主布局文件中添加这些视图JS文件。 You could keep doing the same with the pipeline, however you must add all the files you use to the precompile array: 您可以继续对管道进行操作, 但是必须将使用的所有文件添加到预编译数组中:

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

The assets must be in assets/javascripts but there is no need to add them to the manifest file as you are adding each on individually. 资产必须位于资产/ javascript中,但是无需分别将它们添加到清单文件中。

It is highly recommended that you stick with the Rails defaults for the pipeline and precompile assets for production. 强烈建议您对管道使用Rails的默认值,并为生产预编译资产。

The downside is an extra request on those pages, but this is only an issue if the app is under high load. 缺点是这些页面上的额外请求,但这仅是在应用程序负载高的情况下的问题。

2. The Asset Pipeline Way (TM) 2.资产管道方式(TM)

To do this with the pipeline you would need to move these files into assets/javascripts and require_tree as you say. 要通过管道执行此操作,您需要将这些文件移到资产/ javascript和您所说的require_tree中。

The issue in your case is that the JS snippets target the same class (but with a different post URLs), so this is not going to work. 您遇到的问题是JS代码段针对相同的类(但具有不同的发布URL),因此这行不通。 And with require_tree the order of the files might not be what you want. 使用require_tree,文件的顺序可能不是您想要的。

A new 3.1 app generates files for views (I think), but the expectation is that they will target unique attributes (from a site perspective) in the markup, because all the files get included in the application.js 一个新的3.1应用程序会生成用于视图的文件(我认为),但是期望它们将以标记中的唯一属性(从网站角度)为目标,因为所有文件都包含在application.js中。

To get around the problem of JS clashes. 为了解决JS冲突的问题。 I would suggest that you refactor the JS snippet so that it is more generic. 我建议您重构JS代码段,使其更通用。 You could use a data-post-url attribute on the sortable object: 您可以在可排序对象上使用data-post-url属性:

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

and then collect the url in your JS. 然后在您的JS中收集网址。

Not only is that DRYer, but you have less overall JS and can fully use the pipeline as intended. 不仅是DRYer,而且您的整体JS更少,并且可以按预期充分使用管道。

I'm frustrated on Rails asset pipeline. 我对Rails资产管道感到沮丧。 Maybe not the whole asset pipeline thing but the way Rails organize javascript is really not logical. 也许不是整个资产流水线,但Rails组织javascript的方式确实不合逻辑。

As of now, Rails has a separate javascript file per controller. 到目前为止,Rails每个控制器都有一个单独的javascript文件。 Which is somewhat good in terms of logical organization. 就逻辑组织而言,这有点好。 But then the asset pipeline compresses all those files into one big js file. 但是随后资产管道将所有这些文件压缩为一个大js文件。 So basically your js files are well organized but then they are loaded all at once, resulting to variable clashes, function clashes, other code clashes and other unexpected behavior. 因此,基本上您的js文件组织得很好,但随后一次全部加载了它们,从而导致变量冲突,函数冲突,其他代码冲突和其他意外行为。 Because what we really want as developers is a simple way to execute or load a page specific javascript. 因为我们作为开发人员真正想要的是执行或加载页面特定javascript的简单方法。

One famous approach is to just include a specific javascript file per page. 一种著名的方法是每页仅包含一个特定的javascript文件。 Yes, that will work, but we are not using the performance boost given by the asset pipeline if we are requesting different javascript files per page. 是的,可以,但是如果我们要求每页使用不同的javascript文件,那么我们不会使用资产管道所提供的性能提升。

My solution is to create an javascript object that holds all the page-specific functions then fetch and execute them once the matching controller-action pair is executed by Rails. 我的解决方案是创建一个JavaScript对象,该对象包含所有特定于页面的函数,然后在Rails执行了匹配的控制器-动作对后,提取并执行它们。 Something like this: 像这样:

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

Basically, that's the core idea. 基本上,这就是核心思想。 Well I've implemented that idea and created a gem for it. 好吧,我已经实现了这个想法,并为此创建了一个瑰宝。 Checkout Paloma , and see how you can logically organize your js files and execute page-specific javascript without complex setups. 检出Paloma ,了解如何在不进行复杂设置的情况下逻辑上组织js文件并执行特定于页面的javascript。

Here's an example on how Paloma is used: 这是有关如何使用Paloma的示例:

Javascript file: Javascript文件:

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

Rails controller: Rails控制器:

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

That's just a quick example, but it has lot more to offer, and I'm sure it can solve your problem. 那只是一个简单的例子,但是它提供了更多的东西,我相信它可以解决您的问题。 Easily. 容易。

Thank You! 谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM