3

我已经和其他大学生一起在一个 RoR 项目上工作了几个月。我负责前端和资产部分,我发现自己想知道如何以最佳方式使用 Sprockets

拥有资产管道的目的是在页面加载时间方面提高性能。Rails 生成应用程序的方式是将所有样式表和 javascript 放入两个压缩文件中。

但是,当应用程序的数量和复杂性增加时,恕我直言,这是一个坏主意,因为一体式文件的大小会增加,并且可能存在重叠的 CSS 规则或寻找元素但找不到它的脚本的问题,使页面崩溃的整个 javascript 部分。

注意:我知道,如果团队之间有良好的编码规则和约定,这些问题的发生可以减少,但不会降到 0。

到目前为止,我对这些断言是否正确?

如果是肯定的,那么在不提供大量对页面范围无用的规则或脚本的情况下处理大型项目的好方法是什么,而不会失去发送给客户的少量资产的好处?

我目前的方法是定义一组一体化文件,每个应用程序的“上下文区域”一个。所以基本上我尝试发送 2+2 个文件。

但是如何处理这样的情况:

有一个非常简单的资源索引视图,其中只有条目列表,每个条目都链接到相应的节目。相反,这个节目一点也不简单,它有很多 CSS3 规则和 javascript。

使用我的方法,索引操作将有很多未使用的代码。你如何处理你的大项目?

您更重视页面获得的资源还是性能?

困扰我的另一件事是如何处理 partials。在面向对象的设计中,每个部分都应该(?)包含它需要在加载的任何地方正常工作所需的所有内容。javascript_include_tag但是,如果我在视图和部分中调用相同的资产,这将导致重复的包含。

我的所有这些想法都有意义还是我错过了什么?或者可能是从错误的角度看待问题?你能给我一些链接或开源项目来看看吗?你对此事有何看法?

感谢和抱歉这个长问题。

4

1 回答 1

4

从最佳实践开始(一级代码):

有两个文件,预编译(缩小/压缩),服务于服务器压缩和遥远的未来标头。作为标头的结果,这些文件将在第一次请求时由客户端浏览器缓存,并用于之后的所有页面,直到缓存过期或被清除。

文件也可以被透明代理缓存;ISP 使用这些来为他们的客户加速网络。这将进一步减少请求。

所以从性能的角度来看,只有第一个请求是昂贵的。

管理部分(二级代码)

在具有管理部分的站点中,将其分离成一对单独的文件是很常见的。管理员可能会使用 jquery-ui,而公共站点则不会。在这种情况下,这是最好的折衷方案——您不想为每个公共请求提供一个完全未使用的库。

Rails 管道指南提到了如何设置它。

页面代码(第三层)

第三层是针对特定页面的 js 和 css(你的问题)。

在这种情况下,您将不得不对事物的性能/维护方面进行调用。如果你有很多代码,你想分离出所有这些都必须添加到资产管道预编译数组中。如果有很多或代码很小,这很痛苦。

需要(或想要)这样做可能是向程序员发出的信号,表明 CSS 的整体设计可以改进。如果您必须为特定页面添加大量额外规则,那么您可能没有像您可能那样使用 CASCADE(CSS 中的 C)。:-)

面向对象的 CSS 是解决这个问题的一种方法。作为一个门徒,它是关于定义可以在任何地方使用的可重用 CSS 块。如果这样做了,那么从性能(包括所有页面的规则)或维护的角度来看,少量的页面特定规则就不会成为问题。

如果您必须为页面提供单独的文件,那么遵循这些文件的管道最佳实践至少不会牺牲文件的可缓存性。

我在我的项目中所做的是提供一些帮助程序,允许视图为主应用程序布局堆叠文件和代码。这样做的好处是我可以控制生成的代码出现在哪里,而不是出现在页面中间,如果将文件包含在部分视图中,就会发生这种情况。(这对页面渲染性能非常不利,因为中间页面文件包含块渲染)

我这样做:

application_helper.rb

def deferred_javascript(&block)
  @deferred_javascript ||= []

  if block_given?
    @deferred_javascript << capture(&block)
  end

  @deferred_javascript
end

def deferred_javascript_files
    @javascript_includes ||= []
end

def deferred_css_files
    @stylesheet_includes ||= []
end

然后在一个视图中:

<% deferred_javascript_files << 'extras/public_form' %>
<% deferred_css_files << 'extras/public_form' %>

或者,如果它是单行的,我可以使用带有 deferred_javascript 帮助器的块。(我很少使用这个)。

public_form 文件是此表单(jquery-ui、formtastic)所需内容的清单,在任何其他页面上都不需要。

注意:以这种方式使用的任何文件都必须添加到预编译数组中:

config.assets.precompile += ['extras/public_form.css', 'extras/public_form.js']

很容易忘记,因为我的方法在没有的开发模式下工作,但是在生产中部署时会失败!

最后在应用程序布局中,在 CSS 的顶部(在 head 标签中):

<%= stylesheet_link_tag('application', :media => 'all' ) -%>
<%= stylesheet_link_tag(deferred_css_files) if deferred_css_files.any? %>

在 JS 的布局底部(在结束 body 标记之前):

<%= javascript_tag do %>
  $(document).ready(function() {
<%= raw deferred_javascript.join("\n") %>
  });
<%- end unless deferred_javascript.blank? -%>
<%= javascript_include_tag 'application' %>  
<%= javascript_include_tag(deferred_javascript_files) if deferred_javascript_files.any? %>

此行添加主要清单,以及任何视图清单和代码。

我所概述的内容可确保任何添加视图的文件都是管道的一部分,并且与主文件具有相同的缓存机会。

总结一下:

将所有内容放在主清单中几乎总是正确的做法,但是当特定于页面的代码非常大时,可以将其移动到单独的文件中并按照我的概述提供。您将不得不对哪种方法更好进行性能调用 - 没有在每一页上都有额外的代码,或者在一个页面上没有额外的文件请求。

于 2012-05-12T20:00:30.310 回答