链轮最佳实践大项目

时间:2012-05-12 02:56:36

标签: ruby-on-rails performance optimization asset-pipeline sprockets

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

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

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

注意:我知道,如果团队中有良好的编码规则和惯例,那么这些问题的发生可以减少,但不能降到0。

到目前为止我对这些断言是对的吗?

如果是肯定的那么处理大型项目的好方法是什么,而不会为页面范围提供大量的规则或脚本,而不会丢失少量资产发送给客户的好处? < / p>

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

但接下来如何处理这样的案件:

  

对于只包含条目列表的资源,有一个非常简单的索引视图,每个条目都链接到相应的节目。该节目并不简单,它有很多CSS3规则和javascript。

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

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

困扰我的另一件事是如何处理部分。在面向对象的设计中,每个部分应该(?)具有在加载的任何地方正确工作所需的所有包含。但如果我在视图和部分资源中为同一资产调用javascript_include_tag,则会导致重复包含。

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

感谢和抱歉这个长期的问题。

1 个答案:

答案 0 :(得分: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的布局底部(在关闭体标记之前):

<%= 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? %>

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

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

总结:

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