Rails ActiveStorage:如何避免每个映像进行一次重定向? [英] Rails ActiveStorage: how to avoid one redirect for each image?
问题描述
如果您使用ActiveStorage,并且您的页面中包含N张图片,那么您会向Rails应用程序收到N个额外的请求(即N个重定向).如果页面上有几十个图像,这意味着浪费大量服务器资源.
If you use ActiveStorage and you have a page with N images you get N additional requests to your Rails app (i.e. N redirects). That means wasting a lot of server resources if you have tens of images on a page.
我知道重定向对于签名的URL很有用.但是,我想知道为什么Rails不会预先计算最终的签名URL并将其嵌入到HTML页面中.通过这种方式,我们可以保留签名URL/受保护文件的优点,而无需对Rails服务器进行N次额外的调用.
I know that the redirect is useful for signed URLs. However I wonder why Rails does not precompute the final signed URL and embed that into the HTML page... In this way we could keep the advantages of signed URLs / protected files, without making N additional calls to the Rails server.
是否可以在HTML中直接包含图像变体的最终URL/预签名URL(从而避免重定向)?否则,为什么那不可能呢?
Is it possible to include the final URL / pre-signed URL of image variants directly in the HTML (thus avoiding the redirect)? Otherwise, why is that impossible?
推荐答案
经过几天的推理和测试,我对最终的解决方案感到非常兴奋,下面将对此进行解释.这是一种自以为是的图像处理方法,可能并不代表当前的Rails Way™️,但是对于提供许多公共图像的网站而言,它具有难以置信的优势,尤其是:
After days of reasoning and tests, I am really excited of my final solution, which I explain below. This is an opinionated approach to images and may not represent the current Rails Way™️, however it has incredible advantages for websites that serve many public images, in particular:
- 当您为一个包含N张图片的页面提供服务时,您不会收到对应用服务器的1个+ N个请求,相反,您对该页面只收到1个请求
- 通过CDN提供图像,这可以缩短加载时间
- 存储桶不是完全公开的,而是受Cloudflare保护的
- Cloudflare缓存了图像,这大大减少了您的S3账单
- 您将API请求(即存在)的数量大大减少到S3
- 此解决方案不需要对Rails进行大的更改,因此在出现问题时可以直接切换回Rails的默认行为
- When you serve a page with N images you don't get 1 + N requests to your app server, instead you get only 1 request for the page
- The images are served through a CDN and this improves the loading time
- The bucket is not completely public, instead it is protected by Cloudflare
- The images are cached by Cloudflare, which greatly reduce your S3 bill
- You greatly reduce the number of API requests (i.e. exists) to S3
- This solution does not require large changes to Rails, and thus it is straightforward to switch back to Rails default behavior in case of problems
这是解决方案:
- Create an s3 bucket and configure it to host a public website (i.e. call it
storage.example.com
) - you can even disable the public access at bucket level and allow access only to the Cloudflare ips using a bucket policy - Go to Cloudflare and configure a CNAME for
storage.example.com
that points to your domain; you need to use Flexible SSL (you can use a page rule for the subdomain); use page rules to set heavy caching: set Cache Everything and set a very long value (e.g. 1 year) for Browser Cache TTL and Edge Cache TTL - In you Rails application you can keep using private storage / acl, which is the default Rails behavior
- In your Rails application call
@post.variant(...).processed
after every update or creation of@post
; then in your views use'https://storage.example.com/' + @post.variant(...).key'
(note that we don't callprocessed
here in the views to avoid additional checks in s3); you can also have a rake task that callsprocessed
on each object, in case you need to regenerate the variants; this is works perfectly if you have only a few variants (e.g. 1 image / variant per post) that are changed infrequently
以上大多数步骤都是可选步骤,因此您可以根据需要将它们组合在一起.
Most of the above steps are optional, so you can combine them based on your needs.
这篇关于Rails ActiveStorage:如何避免每个映像进行一次重定向?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!