在Rails生产中,config.assets.compile = true,为什么不呢?

时间:2012-01-11 15:27:27

标签: ruby-on-rails asset-pipeline production-environment

rails new安装的默认Rails应用已生成config.assets.compile = false

通常的做法是在部署应用程序之前运行rake assets:precompile,以确保编译所有资产管道资产。

那么如果我在生产中设置config.assets.compile = true会怎样?

我不再需要运行precompile了。我相信将会发生的是第一次请求资产,它将被编译。这将是第一次出现性能损失(这意味着您通常需要在生产中使用js运行时才能执行此操作)。但除了这些缺点之外,在资产被懒散编译之后,我认为对该资产的所有后续访问都将没有性能受到打击,应用程序的性能将完全在初始首次命中的延迟编译之后,与预编译资产相同的这是真的吗?

有什么我想念的吗?是否有其他原因不在生产中设置config.assets.compile = true?如果我在生产中有一个JS运行时,并且我愿意为资产的第一次访问权衡降级性能,以换取不必运行precompile,这有道理吗?

7 个答案:

答案 0 :(得分:246)

我写了指南的那一点。

你绝对不想在生产中进行编译。

当你编译时,会发生这种情况:

/ assets中对文件的每个请求都会传递给Sprockets。在每个资产的第一个请求中,它被编译并缓存在Rails用于缓存的任何内容中(通常是文件系统)。

在后续请求中,Sprockets接收请求并且必须查找指纹文件名,检查组成资产的文件(图像)或文件(css和js)是否未被修改,然后是否存在缓存版本为此服务。

插件使用的任何供应商/资产文件夹中的资产文件夹中的所有

这是一个很大的开销,说实话,代码没有针对速度进行优化。

这会影响资产通过网络连接到客户端的速度,并会对网站的网页加载时间产生负面影响。

与默认值比较:

当预编译资产并关闭编译时,资产将被编译并指纹识别到public/assets。 Sprockets将普通指纹文件名的映射表返回给Rails,Rails将其写入文件系统。清单文件(Rails 3中的YML或Rails 4中具有随机名称的JSON)在启动时被Rails加载到Memory中,并被缓存以供资产助手方法使用。

这使得生成具有正确指纹资产的页面的速度非常快,并且文件本身的服务本身就是来自文件系统的web-server。两者都比实时编译快得多。

要充分利用管道和指纹识别,您需要在Web服务器上设置远期标头,并为js和css文件启用gzip压缩。 Sprockets会编写gzip压缩版本的资产,您可以将服务器设置为使用,无需为每个请求执行此操作。

这样可以尽可能快地将资产输出到客户端,并以尽可能小的尺寸加速页面的客户端显示,并减少(远期标头)请求。

因此,如果您正在进行实时编译,那么:

  1. 很慢
  2. 缺乏压缩
  3. 会影响页面的渲染时间
  4. 对战

    1. 尽快
    2. 压缩
    3. 从服务器(可选)中删除压缩无意中听到。
    4. 最小化页面的渲染时间。
    5. 编辑:(回复后续评论)

      管道可以在第一次请求时被更改为预编译,但是这样做有一些主要障碍。首先是必须有一个指纹表的查找表,或者辅助方法太慢。在按需编译的情况下,在编译或请求每个新资产时,需要有一些方法可以附加到查找表。

      此外,有人必须在一段未知的时间内支付缓慢资产交付的价格,直到所有资产都汇编到位。

      默认情况下,编译所有内容的价格一次性离线支付,不会影响公众访问者,并确保在事情发生之前一切正常。

      交易破坏者是它为生产系统增加了很多复杂性。

      [编辑,2015年6月] 如果您正在阅读此内容,因为您正在寻找部署期间编译速度慢的解决方案,那么您可以考虑在本地预编译资产。有关这方面的信息位于asset pipeline guide。这允许您仅在存在更改时进行本地预编译,提交,然后进行快速部署而不进行预编译阶段。

答案 1 :(得分:7)

使用Pre-compiling thing减少开销。

Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/

然后您可以在* .html.erb中使用图像和样式表,如“/assets/stylesheet.css” 或“/assets/web.png”

答案 2 :(得分:5)

对于使用Heroku的任何人:

如果部署到Herkou,如果未包含编译资产(即public/assets未提交),它将在部署期间自动为您执行预编译,因此不需要config.assets.compile = true或提交预编译资产。

Heroku的文档是here。建议使用CDN来删除dyno资源上的负载。

答案 3 :(得分:1)

设置config.asset.compile = false

添加到您的Gemfile

group :assets do gem 'turbo-sprockets-rails3' end

安装捆绑包

运行rake assets:precompile

然后启动服务器

答案 4 :(得分:0)

来自官方guide

  

在第一个请求中,资产被编译和缓存,如上面的开发中所述,并且帮助程序中使用的清单名称被更改为包括MD5哈希。

     

Sprockets还将Cache-Control HTTP标头设置为max-age = 31536000。这表示服务器和客户端浏览器之间的所有缓存都表明此内容(所提供的文件)可以缓存1年。这样做的效果是减少从您的服务器请求此资产的次数;资产很有可能位于本地浏览器缓存或某个中间缓存中。

     

此模式使用更多内存,执行速度低于默认值,不推荐使用。

此外,如果您使用Capistrano进行部署,则预编译步骤不会出现问题。它会照顾你。你刚跑完

cap deploy

或(取决于您的设置)

cap production deploy

你已经准备好了。如果您仍然不使用它,我强烈建议您查看它。

答案 5 :(得分:0)

即使在第一次点击之后,它也不会与预编译相同:因为文件未写入文件系统,所以Web服务器无法直接提供这些文件。一些ruby代码将始终涉及,即使它只是读取缓存条目。

答案 6 :(得分:0)

因为它正在打开目录遍历漏洞-https://blog.heroku.com/rails-asset-pipeline-vulnerability