通过 S3 从 Amazon CloudFront 提供 gzip 后的 CSS 和 JavaScript

Posted

技术标签:

【中文标题】通过 S3 从 Amazon CloudFront 提供 gzip 后的 CSS 和 JavaScript【英文标题】:Serving gzipped CSS and JavaScript from Amazon CloudFront via S3 【发布时间】:2011-07-23 10:57:44 【问题描述】:

我一直在寻找加快网站加载速度的方法,而我想探索的一种方法是更多地利用 Cloudfront。

因为 Cloudfront 最初并未设计为自定义来源 CDN,而且它不支持 gzipping,所以到目前为止我一直使用它来托管我的所有图像,这些图像在我的站点代码中由它们的 Cloudfront cname 引用,并且使用远期标头进行了优化。

另一方面,CSS 和 javascript 文件托管在我自己的服务器上,因为直到现在我的印象是无法从 Cloudfront 对它们进行 gzip 处理,而且 gzip 的收益(大约 75% )超过使用 CDN(约 50%):Amazon S3(以及 Cloudfront)不支持通过使用浏览器发送的 HTTP Accept-Encoding 标头以标准方式提供 gzip 压缩的内容,以表明它们支持 gzip压缩,因此他们无法动态压缩和提供组件。

因此,直到现在,我的印象是必须在两种选择之间做出选择:

    将所有资产移至 Amazon CloudFront 并忘记 GZipping;

    保持组件自托管并配置我们的服务器以检测传入请求并在适当的情况下执行动态 GZipping,这是我目前选择做的事情。

个变通方法可以解决这个问题,但基本上这些不起作用。 [link].

现在,Amazon Cloudfront 似乎支持自定义来源,并且如果您使用自定义来源,现在可以使用标准 HTTP Accept-Encoding 方法来提供 gzip 压缩的内容 [link ]。

到目前为止,我还不能在我的服务器上实现新功能。我在上面链接到的博客文章是我发现的唯一详细说明更改的文章,似乎暗示您只能启用 gzipping(条形变通方法,我不想使用),如果您选择自定义来源,我宁愿不这样做:我发现在我的 Cloudfront 服务器上托管相应的文件并从那里链接到它们更简单。尽管仔细阅读了文档,但我不知道:

新功能是否意味着文件应通过自定义来源托管在我自己的域服务器上,如果是,什么代码设置将实现这一点;

如何配置 css 和 javascript 标头以确保它们是从 Cloudfront 压缩的。

【问题讨论】:

【参考方案1】:

更新:亚马逊现在支持 gzip 压缩,因此不再需要。 Amazon Announcement

原答案:

答案是压缩 CSS 和 JavaScript 文件。是的,你没看错。

gzip -9 production.min.css

这将产生production.min.css.gz。删除 .gz,上传到 S3(或您正在使用的任何源服务器)并将文件的 Content-Encoding 标头显式设置为 gzip

这不是即时 gzipping,但您可以非常轻松地将其包装到您的构建/部署脚本中。优点是:

    当请求文件时,Apache 无需 CPU 即可压缩内容。 文件以最高压缩级别压缩(假设为gzip -9)。 您从 CDN 提供文件。

假设您的 CSS/JavaScript 文件 (a) 已缩小并且 (b) 大到足以证明在用户机器上解压缩所需的 CPU 是合理的,那么您可以在此处获得显着的性能提升。

请记住:如果您对 CloudFront 中缓存的文件进行更改,请确保在进行此类更改后使缓存无效。

【讨论】:

看了你的链接后,不得不说博主不知情。 “但是,如果用户确实有一个不支持 gzip 编码的浏览器,那么您网站的压缩样式表和 javascript 将根本不适用于该用户。”这个浏览器可能太旧而无法运行您的样式表和脚本文件。这些用户只占百分之几。 更新:我解决了。它没有显示的原因是我忘记将 Content-Type 设置为 text/css。如果你这样做,你很好,虽然由于某种原因,你似乎无法在 S3 中添加“Accept-Encoding: Vary”标头(这将有助于 Google 速度评级),原因如下所述:@987654322 @]。另外,我设置了 Cache-control 来缓存资产,但它似乎没有缓存它...... 刚刚通过 Google 找到了这个,很抱歉不得不说这不是一个好建议。虽然 桌面 浏览器无法处理压缩内容,但相当多的移动浏览器 不能。多少取决于您正在查看的目标受众;但例如,大多数较旧的诺基亚 S40 都有错误的 gzip 压缩。正确的方法是“自定义源”,它指向一个 Apache/IIS 网络服务器,该服务器执行内容压缩并提供正确的 HTTP 标头。这是一篇描述其要点的博客文章:nomitor.com/blog/2010/11/10/… 2015 年初的情况如何? @JesperMortensen 和 Simon Peck 发布的链接是否仍然相关? 亚马逊在 2015 年 12 月宣布支持 gzip 压缩,所以现在这无关紧要,只需上传基本文件即可。 aws.amazon.com/blogs/aws/…【参考方案2】:

您可以将 CloudFront 配置为自动压缩某些类型的文件并提供压缩文件。

请参阅 AWS Developer Guide

【讨论】:

您能否添加有关您的解决方案的更多信息(可能是一个示例)以使其成为更好的答案。【参考方案3】:

Cloudfront 支持 gzip。

Cloudfront 通过 HTTP 1.0 连接到您的服务器。默认情况下,包括 nginx 在内的一些网络服务器不向 HTTP 1.0 连接提供压缩内容,但您可以通过添加以下内容来告诉它:

gzip_http_version 1.0

到你的 nginx 配置。可以为您使用的任何 Web 服务器设置等效配置。

这确实具有使保持活动连接不适用于 HTTP 1.0 连接的副作用,但由于压缩的好处是巨大的,因此绝对值得权衡。

取自http://www.cdnplanet.com/blog/gzip-nginx-cloudfront/

编辑

通过亚马逊云前端提供动态压缩的内容是危险的,可能不应该这样做。基本上,如果您的网络服务器正在压缩内容,它不会设置 Content-Length,而是将数据作为分块发送。

如果 Cloudfront 和您的服务器之间的连接中断并过早断开,Cloudfront 仍会缓存部分结果并将其作为缓存版本提供,直到过期。

首先在磁盘上对其进行 gzip 压缩然后提供 gzip 压缩版本的公认答案是一个更好的主意,因为 Nginx 将能够设置 Content-Length 标头,因此 Cloudfront 将丢弃截断的版本。

【讨论】:

-1,这个答案与问题无关。 Nginx != S3 和 Cloudfront @Danack,您是否因为这个问题而在 Cloudfront 缓存半检索文件时遇到很多问题?我试图了解这在实践中对您来说有多大的问题。 @poshest 它发生了。即时提供 gzipped 几乎没有什么好处(因为 gzip 在服务器上的速度非常快),所以我一看到它就关闭了它。在 gzip 格式的内容尚不存在的极少数情况下,与“第一个字节的时间”慢 200 毫秒相比,损坏的数据是一个更大的问题。 如果资产在标头中缺少 Content-Length 属性但包含 Transfer-Encoding: chunked (通常使用 gzip 压缩的资产),CloudFront 将不会缓存部分资产t 接收一个终止块。如果缺少这两个属性,则可能会缓存不完整的资产。见:docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…【参考方案4】:

我的回答是:http://blog.kenweiner.com/2009/08/serving-gzipped-javascript-files-from.html

根据斯凯勒的回答,您可以上传 gzip 和非 gzip 版本的 css 和 js。在 Safari 中小心命名和测试。因为 safari 不会处理 .css.gz.js.gz 文件。

site.jssite.js.jgzsite.csssite.gz.css(您需要将 content-encoding 标头设置为正确的 MIME 类型才能正确提供这些信息)

然后在你的页面放。

<script type="text/javascript">var sr_gzipEnabled = false;</script> 
<script type="text/javascript" src="http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr.gzipcheck.js.jgz"></script> 

<noscript> 
  <link type="text/css" rel="stylesheet" href="http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css">
</noscript> 
<script type="text/javascript"> 
(function () 
    var sr_css_file = 'http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css';
    if (sr_gzipEnabled) 
      sr_css_file = 'http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css.gz';
    

    var head = document.getElementsByTagName("head")[0];
    if (head) 
        var scriptStyles = document.createElement("link");
        scriptStyles.rel = "stylesheet";
        scriptStyles.type = "text/css";
        scriptStyles.href = sr_css_file;
        head.appendChild(scriptStyles);
        //alert('adding css to header:'+sr_css_file);
     
());
</script> 

gzipcheck.js.jgz 就是 sr_gzipEnabled = true; 这个测试是为了确保浏览器可以处理 gzip 压缩的代码,如果不能处理则提供备份。

然后在页脚中执行类似的操作,假设您的所有 js 都在一个文件中并且可以进入页脚。

<div id="sr_js"></div> 
<script type="text/javascript"> 
(function () 
    var sr_js_file = 'http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr-br-min.js';
    if (sr_gzipEnabled) 
       sr_js_file = 'http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr-br-min.js.jgz';
    
    var sr_script_tag = document.getElementById("sr_js");         
    if (sr_script_tag) 
    var scriptStyles = document.createElement("script");
    scriptStyles.type = "text/javascript";
    scriptStyles.src = sr_js_file;
    sr_script_tag.appendChild(scriptStyles);
    //alert('adding js to footer:'+sr_js_file);
    
());
</script> 

更新:亚马逊现在支持 gzip 压缩。公告,因此不再需要。 Amazon Announcement

【讨论】:

非常感谢您的建议。如果我对您的理解正确,您正在解决用户的浏览器无法读取 gzip 压缩文件的情况,尽管它现在涉及的浏览器比例相当小,但仍然可能发生这种情况。如果您参考我在我的问题[link] 中发布的链接,此解决方案的一个可能缺点是这意味着您无法缓存您的页面,因为它只有在您的代码每次用户都动态运行时才有效加载页面(当然是我的)。 @DonaldJenkins 我认为 js 仍然会被缓存。当您在 js 片段中构建脚本标签时,仍然必须调用 js,我相信如果它在缓存中,浏览器会从那里使用它。 测试页面blog.kosny.com/testpages/safari-gz表示警告“在Safari中命名和测试要小心。因为safari不会处理css.gz或js.gz”已过期。在 Mavericks 的 Safari 7 和 ios 7 的 Safari 中,css.gz 和 js.gz 都可以工作。我不知道这个变化是什么时候发生的,我只是用我拥有的设备进行测试。【参考方案5】:

昨天亚马逊宣布了新功能,您现在可以在您的发行版上启用 gzip。

它可以与 s3 一起使用,而无需自己添加 .gz 文件,我今天尝试了新功能,效果很好。 (但需要使您的当前对象无效)

More info

【讨论】:

【参考方案6】:

我们最近对 uSwitch.com 进行了一些优化,以压缩我们网站上的一些静态资产。虽然我们设置了一个完整的 nginx 代理来执行此操作,但我还组装了一个小 Heroku 应用程序,它在 CloudFront 和 S3 之间进行代理以压缩内容:http://dfl8.co

鉴于可以使用简单的 URL 结构访问可公开访问的 S3 对象,http://dfl8.co 仅使用相同的结构。 IE。以下 URL 是等效的:

http://pingles-example.s3.amazonaws.com/sample.css
http://pingles-example.dfl8.co/sample.css
http://d1a4f3qx63eykc.cloudfront.net/sample.css

【讨论】:

以上是关于通过 S3 从 Amazon CloudFront 提供 gzip 后的 CSS 和 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章

使用 .htaccess 从 Amazon S3 CloudFront 访问服务器文件

Gzip 与 Amazon S3/Cloudfront 失败

Amazon S3 + CloudFront 查询特定版本的存储文件

为啥需要 Amazon S3 和 Cloudfront?

Amazon S3 是不是向 CloudFront 发送失效信号?

Amazon Cloudfront 缓存问题