Rails ActiveStorage:如何避免对每张图片进行一次重定向?
Rails ActiveStorage: how to avoid one redirect for each image?
如果您使用 ActiveStorage 并且您有一个包含 N 个图像的页面,您会收到对 Rails 应用程序的 N 个额外请求(即 N 个重定向)。如果一个页面上有数十张图片,这意味着会浪费大量服务器资源。
我知道重定向对已签名的 URL 很有用。但是我想知道为什么 Rails 不预先计算最终签名的 URL 并将其嵌入到 HTML 页面中......这样我们就可以保持签名 URLs 的优势/ 保护文件,无需对 Rails 服务器进行 N 次额外调用。
是否可以在 HTML 中直接包含最终 URL / 预签名 URL 图像变体(从而避免重定向)?否则,为什么不可能?
您可以使用 service_url
创建指向您的资源的直接链接。
我们不在我们的项目中使用 Rails 视图,所以我对视图层的了解很生疏。我想你可以把它放在一个专门的帮助程序中,然后从你的视图中使用它。
经过几天的推理和测试,我对我的最终解决方案感到非常兴奋,我将在下面解释。这是一种固执己见的图像处理方法,可能不代表当前的 Rails Way™️,但它对于提供许多 public 图片的网站具有不可思议的优势,特别是:
- 当您提供包含 N 张图片的页面时,您不会收到对应用服务器的 1 + N 次请求,而只会收到 1 次页面请求
- 图像通过 CDN 提供,这缩短了加载时间
- 存储桶不完全 public,而是受 Cloudflare
保护
- 图片由 Cloudflare 缓存,大大降低您的 S3 费用
- 您大大减少了对 S3API 请求(即存在)的数量
- 此解决方案不需要对 Rails 进行大量更改,因此在出现问题时可以直接切换回 Rails 默认行为
解决方法如下:
- 创建一个 s3 存储桶并将其配置为 host a public website(即称之为
storage.example.com
)——您甚至可以在存储桶级别禁用 public 访问并仅允许访问 Cloudflare使用存储桶策略的 ips
- 转到 Cloudflare 并为
storage.example.com
配置指向您域的 CNAME;您需要使用 Flexible SSL(您可以为子域使用页面规则);使用页面规则设置大量缓存:设置 Cache Everything 并为 Browser Cache TTL 和 Edge Cache TTL 设置一个非常长的值(例如 1 年)
- 在您的 Rails 应用程序中,您可以继续使用私有存储/acl,这是默认的 Rails 行为
- 在您的 Rails 应用程序中,每次更新或创建
@post
后调用 @post.variant(...).processed
;然后在您的视图中使用 'https://storage.example.com/' + @post.variant(...).key'
(请注意,我们不会在视图中调用 processed
以避免在 s3 中进行额外检查);你也可以有一个在每个对象上调用 processed
的 rake 任务,以防你需要重新生成变体;如果您只有少数不经常更改的变体(例如,每个 post 1 个图像/变体) ,这将非常有效
以上大部分步骤是可选的,因此您可以根据需要组合它们。
如果您使用 ActiveStorage 并且您有一个包含 N 个图像的页面,您会收到对 Rails 应用程序的 N 个额外请求(即 N 个重定向)。如果一个页面上有数十张图片,这意味着会浪费大量服务器资源。
我知道重定向对已签名的 URL 很有用。但是我想知道为什么 Rails 不预先计算最终签名的 URL 并将其嵌入到 HTML 页面中......这样我们就可以保持签名 URLs 的优势/ 保护文件,无需对 Rails 服务器进行 N 次额外调用。
是否可以在 HTML 中直接包含最终 URL / 预签名 URL 图像变体(从而避免重定向)?否则,为什么不可能?
您可以使用 service_url
创建指向您的资源的直接链接。
我们不在我们的项目中使用 Rails 视图,所以我对视图层的了解很生疏。我想你可以把它放在一个专门的帮助程序中,然后从你的视图中使用它。
经过几天的推理和测试,我对我的最终解决方案感到非常兴奋,我将在下面解释。这是一种固执己见的图像处理方法,可能不代表当前的 Rails Way™️,但它对于提供许多 public 图片的网站具有不可思议的优势,特别是:
- 当您提供包含 N 张图片的页面时,您不会收到对应用服务器的 1 + N 次请求,而只会收到 1 次页面请求
- 图像通过 CDN 提供,这缩短了加载时间
- 存储桶不完全 public,而是受 Cloudflare 保护
- 图片由 Cloudflare 缓存,大大降低您的 S3 费用
- 您大大减少了对 S3API 请求(即存在)的数量
- 此解决方案不需要对 Rails 进行大量更改,因此在出现问题时可以直接切换回 Rails 默认行为
解决方法如下:
- 创建一个 s3 存储桶并将其配置为 host a public website(即称之为
storage.example.com
)——您甚至可以在存储桶级别禁用 public 访问并仅允许访问 Cloudflare使用存储桶策略的 ips - 转到 Cloudflare 并为
storage.example.com
配置指向您域的 CNAME;您需要使用 Flexible SSL(您可以为子域使用页面规则);使用页面规则设置大量缓存:设置 Cache Everything 并为 Browser Cache TTL 和 Edge Cache TTL 设置一个非常长的值(例如 1 年) - 在您的 Rails 应用程序中,您可以继续使用私有存储/acl,这是默认的 Rails 行为
- 在您的 Rails 应用程序中,每次更新或创建
@post
后调用@post.variant(...).processed
;然后在您的视图中使用'https://storage.example.com/' + @post.variant(...).key'
(请注意,我们不会在视图中调用processed
以避免在 s3 中进行额外检查);你也可以有一个在每个对象上调用processed
的 rake 任务,以防你需要重新生成变体;如果您只有少数不经常更改的变体(例如,每个 post 1 个图像/变体) ,这将非常有效
以上大部分步骤是可选的,因此您可以根据需要组合它们。