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


185

已安装的默认Rails应用rails newconfig.assets.compile = false在生产中。

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

那么,如果我开始config.assets.compile = true生产该怎么办?

precompile不再需要跑步了。我认为将会发生的是第一次请求资产时,将对其进行编译。这将是第一次降低性能(这意味着您通常需要在生产环境中使用js运行时才能做到)。但是除了这些缺点之外,在对资产进行延迟编译之后,我认为对该资产的所有后续访问都不会影响性能,该应用程序的性能将与在此初始首次命中的延迟编译之后的预编译资产完全相同这是真的?

有什么我想念的吗?还有其他原因不适合config.assets.compile = true生产吗?如果我已经在生产环境中使用了JS运行时,并且愿意为资产的首次访问权衡性能下降的代价,而不必运行它precompile,这是否有意义?


1
警告,旧版本的链轮存在一个bug,如果config.assets.compile配置为真正有目录trasversal漏洞的风险(blog.heroku.com/rails-asset-pipeline-vulnerability
莫罗

这正是Stackoverflow应该工作的方式。一个写得很好的问题和一个写得很好的答案。我爱你们op和@ richard-hulse。
schmijos

Answers:


259

我写了那本指南。

您绝对不希望在生产中进行实时编译。

当您进行编译时,将发生以下情况:

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

在随后的请求中,Sprockets接收到该请求,并且必须查找指纹文件名,检查构成资产的文件(图像)或文件(css和js)是否未修改,然后如果有缓存版本,则为该文件提供服务。

这是一切的资产文件夹,并在任何供应商/使用插件资产的文件夹。

坦白说,这是很多开销,因为代码并未针对速度进行优化。

这将影响资产通过电线快速传输到客户端的速度,并对站点的页面加载时间产生负面影响。

与默认值比较:

当资产被预编译并关闭编译时,资产将被编译并指纹到public/assets。Sprockets将平原到指纹文件名的映射表返回到Rails,Rails将此表写入文件系统。清单文件(在Rails 3中为YML或在Rails 4中为随机名称的JSON)在启动时由Rails加载到内存中,并缓存以供资产帮助器方法使用。

这使得具有正确指纹资产的页面的生成非常快,并且文件本身的提供是从文件系统Web服务器快速进行的。两者都比实时编译快得多。

为了最大程度地利用流水线和指纹识别功能,您需要在Web服务器上设置远期头,并为js和css文件启用gzip压缩。Sprockets编写资产的压缩版本,您可以将其设置为使用服务器,而无需为每个请求都这样做。

这样可以尽可能快地以最小的大小将资产提供给客户端,从而加快了客户端在页面上的显示速度,并减少了请求(具有远期头)。

因此,如果您正在现场编译,它是:

  1. 非常慢
  2. 缺乏压缩
  3. 将影响页面的渲染时间

  1. 尽可能快
  2. 压缩的
  3. 从服务器(可选)上删除压缩窃听。
  4. 最小化页面的渲染时间。

编辑:(回答跟进评论)

该管道可以改为预编译的第一个请求,但也有一些主要的障碍这样做。首先是必须有一个用于查找指纹名称的查找表,否则辅助方法太慢。在按需编译的环境下,当每种新资产被编译或请求时,将需要某种方式附加到查找表。

而且,在所有资产被编译并就位之前,有人将不得不为资产交付缓慢的时间付出未知的时间。

缺省情况下,一次编译所有内容的费用是脱机支付的,它不会影响公众访问者,并确保一切在事情上线之前就起作用。

令人大跌眼镜的是,它给生产系统增加了很多复杂性。

[2015年6月,编辑]如果由于正在寻找解决方案以减少部署期间的缓慢编译时间而阅读此书,则可以考虑在本地预编译资产。有关此信息,请参阅资产管道指南。这使您仅在发生更改时才在本地进行预编译,提交更改,然后在没有预编译阶段的情况下进行快速部署。


1
谢谢,我已经接受了您的回答。但是现在我的问题是,好吧,它现在还不做,但是可以想象,您是否认为Asset Pipeline 可以具有一个功能,可以在首次请求时延迟进行编译,就像预编译一样,包括写入./public和更新指纹清单?
jrochkind 2012年

往上看。因为Capistrano对您不起作用,这是一个问题吗?
理查德·赫尔瑟

我不使用Capistrano。我以前不需要,增加的复杂性是不值得的。也许资产管道是将骆驼折断并需要它的稻草。您认为通过资产管道管理Rails部署是不可行的没有或类似?真可惜,对于简单的设置来说,过去手工完成并不是什么大问题。
jrochkind 2012年

您确实确实需要Capistrano for Rails 3.1。当您的旧应用仍在运行时,资产将被编译到新的公共目录中。编译完成后,将对新版本进行符号链接,并自动重新启动服务器。
理查德·霍尔斯

“要获得管道和指纹识别的最大优势,您需要在Web服务器上设置远距离的标头,并为js和css文件启用gzip压缩。”-请您提供一些说明或链接以了解操作方法这个?
艾萨克·贝特什

7

为了减少预编译的开销。

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

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


6

对于使用Heroku的任何人:

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

Heroku的文档在这里。建议使用CDN消除dyno资源上的负载。


1

即使在第一次命中之后,它也不会与预编译相同:因为文件未写入文件系统,因此无法由Web服务器直接提供。即使只读取缓存条目,也总是会涉及一些红宝石代码。


嗯,我认为使用precompile=true,已编译的资产将被写入文件系统。你确定吗?让我检查一下...
jrochkind 2012年

1
ah,我认为您是对的-它们已写入文件系统,但看起来好像是tmp/cache而不是public/assets,因此它不是Web服务器可以看到的地方,它们仍将由Rails应用提供服务Web服务器。等等。您认为正确吗?
jrochkind 2012年

正确。不会像让Web服务器立即将它们选中一样快。如果你把一个CDN像CloudFront的在您的应用程序前可能没有关系
弗雷德里克祥

1

config.asset.compile = false

添加到您的Gemfile

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

安装套件

rake assets:precompile

然后启动服务器


据我已经设置config.asset.compile = true in production.rb文件,因为没有添加预完成机制。因此,每次启动服务器时,加载页面都花费了太多时间(当请求命中时,既处理请求又编译资产)。现在,我将其包含turbo-sprockets-rails3在Gemfile中并运行命令,该命令rake assets:precompile将事先编译资产。现在我设置config.asset.compile = false in production.rb并启动服务器,页面加载没有任何延迟。(仅处理请求而不进行资产编译)
Mohammed Saleem 2014年

2
值得一说的turbo-sprockets-rails3是,只有在Ruby 3上才有必要
Andre Figueiredo

0

从官方指南

在第一个请求上,资产如上面的开发概述中所述进行编译和缓存,并且更改了助手中使用的清单名称,以包括MD5哈希。

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

此模式使用更多内存,性能比默认模式差,因此不建议这样做。

而且,如果您使用Capistrano进行部署,那么预编译步骤根本就不会麻烦。它为您照顾。你刚跑

cap deploy

或(取决于您的设置)

cap production deploy

你们都准备好了。如果您仍然不使用它,我强烈建议您检查一下。


那么您认为官方指南中的语言与我一致吗?我看过该指南,但不确定它是否代表我上面的建议,您对此有何看法?那是我的问题。
jrochkind 2012年

是的,您说的基本上是同一回事。我建议您不要打开实时编译。
塞尔吉奥·图伦采夫2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.