我通过将我的 JavaScript 应用程序 (SPA) 上传到 S3(默认根对象 index.html 和 Cache-Control:max-age=0,无缓存,指向指纹 js/css Assets )并将其配置为一个源到 CloudFront 分配。我的域名,比如说 SomeMusicPlatform.com 在 Route53 中有一个包含分发 URL 的 CNAME 条目。这很好用,并且都很好地缓存。
现在我想为机器人和社交网络爬虫提供一个预渲染的 HTML 版本。我已经设置了一个服务器,该服务器在域 处响应 JavaScript 应用程序 (SPA) 的预渲染版本。 prerendered.SomeMusicPlatform.com .
我在 lambda 函数中尝试做的是检测用户代理,识别机器人并为它们提供来自我的自定义服务器的预渲染版本(而不是我通常为常规浏览器提供的来自 S3 的 JavaScript 内容)。
我想我可以通过使用 Lambda@Edge: Using an Origin-Request Trigger to Change From an Amazon S3 Origin to a Custom Origin 来实现这一点。函数将源切换到我的自定义预渲染服务器,以防它在响应 header 中识别爬虫机器人(或者,在测试阶段,使用 prerendered=true
查询参数)。
问题是带有 Lambda@Edge 函数的 Origin-Request 触发器没有触发,因为 CloudFront 仍然具有默认根对象 index.html
缓存并倾向于从缓存边缘返回内容。我收到 X-Cache:RefreshHit from cloudfront
通过同时使用 SomeMusicPlatform.com/?prerendered=true
和 SomeMusicPlatform.com
,即使有 Cache-Control:max-age=0, no-cache
在默认根对象 - index.html 上。
如何使用 CloudFront 保持 JavaScript SPA 的良好缓存服务和低延迟,并为爬虫机器人添加来自自定义预渲染服务器的服务内容?
最佳答案
通过添加 mywebsite.com/?prerendered=true
解决了缓存问题(使用 mywebsite.com
或 prerendered
时获得相同的命中)到 cloudfront 分发中的查询白名单。这意味着 CloudFront 现在可以正确维护网站内容的正常版本和预渲染版本,具体取决于参数的存在(不提供来自 S3 源的参数缓存内容,以及来自我的自定义源的参数缓存内容在 lambda 函数中指定送达)。
这对于测试阶段来说已经足够了 - 以确保机制正常工作。然后我按照 Michael 的建议在 Viewer Request 触发器中添加了另一个 lambda 函数,它添加了一个自定义 header Is-Bot
如果在 User-Agent
中检测到机器人.同样,需要白名单,这一次是针对自定义 header (根据自定义 header 维护两个源的缓存)。源请求触发器中稍后的另一个 lambda 函数然后决定使用哪个源,具体取决于 Is-Bot
标题。
关于amazon-s3 - Cloudfront 和 Lambda@Edge - 根据用户代理从自定义来源获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47517987/