Ruby-on-rails config.assets.compile=true 在 Rails 生产中,为什么不呢?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8821864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
config.assets.compile=true in Rails production, why not?
提问by jrochkind
The default Rails app installed by rails newhas config.assets.compile = falsein production.
安装的默认 Rails 应用程序rails new已config.assets.compile = false投入生产。
And the ordinary way to do things is to run rake assets:precompilebefore deploying your app, to make sure all asset pipeline assets are compiled.
通常的做法是rake assets:precompile在部署应用程序之前运行,以确保所有资产管道资产都已编译。
So what happens if I set config.assets.compile = truein production?
那么如果我config.assets.compile = true在生产中设置会发生什么?
I wont' need to run precompileanymore. What I believewill happen is the first time an asset is requested, it will be compiled. This will be a performance hit that first time (and it means you generally need a js runtime in production to do it). But other than these downsides, after the asset was lazily compiled, I thinkall subsequent access to that asset will have noperformance hit, the app's performance will be exactly the sameas with precompiled assets after this initial first-hit lazy compilation. is this true?
我不需要再跑precompile了。我相信会发生的是第一次请求资产时,它将被编译。这将是第一次的性能损失(这意味着您通常需要在生产中使用 js 运行时才能做到这一点)。但是除了这些缺点之外,在资产被延迟编译之后,我认为对该资产的所有后续访问都不会影响性能,应用程序的性能将与在初始首次命中延迟编译后的预编译资产完全相同。这是真的?
Is there anything I'm missing? Any other reasons not to set config.assets.compile = truein production? If I've got a JS runtime in production, and am willing to take the tradeoff of degraded performance for the firstaccess of an asset, in return for not having to run precompile, does this make sense?
有什么我想念的吗?还有什么其他原因不能config.assets.compile = true在生产中设置吗?如果我在生产环境中有一个 JS 运行时,并且愿意在第一次访问资产时权衡性能下降,以换取不必运行precompile,这是否有意义?
回答by Richard Hulse
I wrote that bit of the guide.
我写了那一点指南。
You definitely do not want to live compile in production.
您绝对不想在生产中进行实时编译。
When you have compile on, this is what happens:
当您进行编译时,会发生以下情况:
Every request for a file in /assets is passed to Sprockets. On the firstrequest for each and every asset it is compiled and cached in whatever Rails is using for cache (usually the filesystem).
/assets 中的每个文件请求都会传递给 Sprockets。在对每个资产的第一次请求时,它被编译并缓存在 Rails 用于缓存的任何地方(通常是文件系统)中。
On subsequent requests Sprockets receives the request and has to look up the fingerprinted filename, check that the file (image) or files(css and js) that make up the asset were not modified, and then if there is a cached version serve that.
在后续请求中,链轮接收请求并必须查找指纹文件名,检查构成资产的文件(图像)或文件(css 和 js)是否未被修改,然后如果有缓存版本,则提供该文件。
That is everythingin the assets folder andin any vendor/assets folders used by plugins.
这是一切的资产文件夹,并在任何供应商/使用插件资产的文件夹。
That is a lot of overhead as, to be honest, the code is not optimized for speed.
这是很多开销,因为老实说,代码没有针对速度进行优化。
This will have an impact on how fast asset go over the wire to the client, and will negatively impact the page load times of your site.
这将对资产通过线路传输到客户端的速度产生影响,并对您网站的页面加载时间产生负面影响。
Compare with the default:
与默认值比较:
When assets are precompiled and compile is off, assets are compiled and fingerprinted to the public/assets. Sprockets returns a mapping table of the plain to fingerprinted filenames to Rails, and Rails writes this to the filesystem. The manifest file (YML in Rails 3 or JSON with a randomised name in Rails 4) is loaded into Memory by Rails at startup and cached for use by the asset helper methods.
当资产被预编译并且编译关闭时,资产被编译并指纹到public/assets. Sprockets 将普通文件名到指纹文件名的映射表返回给 Rails,Rails 将其写入文件系统。清单文件(Rails 3 中的 YML 或 Rails 4 中具有随机名称的 JSON)在启动时由 Rails 加载到内存中,并缓存以供资产助手方法使用。
This makes the generation of pages with the correct fingerprinted assets very fast, and the serving of the files themselves are web-server-from-the-filesystem fast. Both dramatically faster than live compiling.
这使得具有正确指纹资产的页面的生成速度非常快,并且文件本身的服务是来自文件系统的快速网络服务器。两者都比实时编译快得多。
To get the maximum advantage of the pipeline and fingerprinting, you need to set far-future headers on your web server, and enable gzip compression for js and css files. Sprockets writes gzipped versions of assets which you can set your server to use, removing the need for it to do so for each request.
要获得管道和指纹识别的最大优势,您需要在 Web 服务器上设置远未来的标头,并为 js 和 css 文件启用 gzip 压缩。Sprockets 编写了 gzip 压缩版本的资产,您可以将这些资产设置为使用这些资产,从而无需为每个请求都这样做。
This get assets out to the client as fast as possible, and in the smallest size possible, speeding up client-side display of the pages, and reducing (with far-future header) requests.
这将尽快将资产以尽可能小的尺寸提供给客户端,从而加快页面的客户端显示速度,并减少(使用远期标题)请求。
So if you are live compiling it is:
因此,如果您正在实时编译,则它是:
- Very slow
- Lacks compression
- Will impact render time of pages
- 非常慢
- 缺乏压缩
- 会影响页面的渲染时间
Versus
相对
- As fast as possible
- Compressed
- Remove compression overheard from server (optionally).
- Minimize render time of pages.
- 尽可能快地
- 压缩的
- 删除从服务器中听到的压缩(可选)。
- 最小化页面的渲染时间。
Edit: (Answer to follow up comment)
编辑:(回答跟进评论)
The pipeline couldbe changed to precompile on the first request but there are some major roadblocks to doing so. The first is that there has to be a lookup table for fingerprinted names or the helper methods are too slow. Under a compile-on-demand senario there would need to be some way to append to the lookup table as each new asset is compiled or requested.
管道可以更改为在第一个请求时预编译,但这样做有一些主要障碍。首先是必须有一个用于指纹名称的查找表或辅助方法太慢。在按需编译的情况下,需要通过某种方式在编译或请求每个新资产时附加到查找表。
Also, someone would have to pay the price of slow asset delivery for an unknown period of time until all the assets are compiled and in place.
此外,在所有资产都被编译和到位之前,有人将不得不为一段未知的时间段内缓慢的资产交付付出代价。
The default, where the price of compiling everything is paid off-line at one time, does not impact public visitors and ensures that everything works before things go live.
默认情况下,编译所有内容的价格一次离线支付,不会影响公众访问者并确保一切正常运行。
The deal-breaker is that it adds a lot of complexity to production systems.
交易破坏者是它给生产系统增加了很多复杂性。
[Edit, June 2015]If you are reading this because you are looking for a solution for slow compile times during a deploy, then you could consider precompiling the assets locally. Information on this is in the asset pipeline guide. This allows you to precompile locally only when there is a change, commit that, and then have a fast deploy with no precompile stage.
[编辑,2015 年 6 月]如果您正在阅读本文是因为您正在寻找部署期间编译时间缓慢的解决方案,那么您可以考虑在本地预编译资产。有关这方面的信息在资产管道指南中。这允许您仅在发生更改时在本地预编译,提交该更改,然后在没有预编译阶段的情况下进行快速部署。
回答by dbKooper
To have less overhead with Pre-compiling thing.
减少预编译的开销。
Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/
you can then simply use images and stylesheets as as "/assets/stylesheet.css" in *.html.erb or "/assets/web.png"
然后,您可以简单地将图像和样式表用作 *.html.erb 或“/assets/web.png”中的“/assets/stylesheet.css”
回答by William Denniss
For anyone using Heroku:
对于任何使用 Heroku 的人:
If you deploy to Herkou, it will do the precompile for you automatically during the deploy if compiled assets are not included (i.e. public/assetsnot committed) so no need for config.assets.compile = true, or to commit the precompiled assets.
如果你部署到 Herkou,它会在部署期间自动为你做预编译,如果编译的资产没有被包含(即public/assets未提交),所以不需要config.assets.compile = true, 或提交预编译的资产。
Heroku's docs are here. A CDNis recommended to remove the load on the dyno resource.
回答by Mohammed Saleem
Set config.asset.compile = false
放 config.asset.compile = false
Add to your Gemfile
添加到您的 Gemfile
group :assets do
gem 'turbo-sprockets-rails3'
end
group :assets do
gem 'turbo-sprockets-rails3'
end
Install the bundle
安装捆绑包
Run rake assets:precompile
跑 rake assets:precompile
Then Start your server
然后启动你的服务器
回答by Frederick Cheung
It won't be the same as precompiling, even after that first hit: because the files aren't written to the filesystem they can't be served directly by the web server. Some ruby code will always be involved, even if it just reads a cache entry.
它与预编译不同,即使在第一次命中之后:因为文件没有写入文件系统,它们不能直接由 Web 服务器提供服务。总会涉及一些 ruby 代码,即使它只是读取缓存条目。
回答by Sergio Tulentsev
From the official guide:
从官方指南:
On the first request the assets are compiled and cached as outlined in development above, and the manifest names used in the helpers are altered to include the MD5 hash.
Sprockets also sets the Cache-Control HTTP header to max-age=31536000. This signals all caches between your server and the client browser that this content (the file served) can be cached for 1 year. The effect of this is to reduce the number of requests for this asset from your server; the asset has a good chance of being in the local browser cache or some intermediate cache.
This mode uses more memory, performs poorer than the default and is not recommended.
在第一个请求中,资产按照上述开发中的概述进行编译和缓存,并且帮助程序中使用的清单名称被更改为包括 MD5 哈希。
Sprockets 还将 Cache-Control HTTP 标头设置为 max-age=31536000。这会向您的服务器和客户端浏览器之间的所有缓存发出信号,表明此内容(所提供的文件)可以缓存 1 年。这样做的效果是减少您的服务器对该资产的请求数量;该资产很有可能位于本地浏览器缓存或某些中间缓存中。
此模式使用更多内存,性能比默认模式差,不推荐使用。
Also, precompile step is not trouble at all if you use Capistranofor your deploys. It takes care of it for you. You just run
此外,如果您使用Capistrano进行部署,预编译步骤一点也不麻烦。它会为你照顾它。你就跑
cap deploy
or (depending on your setup)
或(取决于您的设置)
cap production deploy
and you're all set. If you still don't use it, I highly recommend checking it out.
你已经准备好了。如果您仍然不使用它,我强烈建议您检查一下。
回答by Aurel Branzeanu
Because it is opening a directory traversal vulnerability - https://blog.heroku.com/rails-asset-pipeline-vulnerability
因为它开启了一个目录遍历漏洞——https: //blog.heroku.com/rails-asset-pipeline-vulnerability

