如何在 .htaccess 文件中指定 "Vary: Accept-Encoding" 头部信息

81

谷歌页面速度建议我在JS和CSS中“指定 Vary: Accept-Encoding头部信息”。我该如何在 .htaccess 文件中实现此功能?


23
不确定为什么这个被关闭了,仅仅因为它不涉及编程语言并不意味着它与编码无关。 - BlueRaja - Danny Pflughoeft
@BlueRaja-DannyPflughoeft 我同意,这个话题已经被浏览了超过65100次,所以我认为这是一个受欢迎的话题,更不用说我每天都回答htaccess相关问题。 - Panama Jack
我知道这听起来很枯燥,但是头文件 Vary: Accept-Encoding 将告诉浏览器根据 Content-Encoding 头文件在缓存中存储页面的版本。您可以查看 https://dev59.com/53I-5IYBdhLWcg3wMFS0 和 https://developers.google.com/speed/docs/best-practices/caching?hl=sv&csw=1#LeverageProxyCaching - Ismael Miguel
2
@IsmaelMiguel,这实际上会告诉客户端(更重要的是,在路上的任何缓存服务器),该文件与客户端的Accept-Encoding请求头值的每个变体不同,而不是服务器响应头值的每个Content-Encoding变体。 - aularon
@BlueRaja-DannyPflughoeft 因为那些声望很高的用户和那些想要提高声望的用户通过寻找需要关闭的问题来建立声望。令人沮丧的是,这经常导致本不应该关闭的问题被关闭。 - Dan Nissenbaum
7个回答

90

我猜这意味着你要为你的CSS和JS文件启用gzip压缩,因为这将使客户端能够接收到gzip编码的内容和纯文本内容。

以下是在apache2中执行此操作的方法:

<IfModule mod_deflate.c>
    #The following line is enough for .js and .css
    AddOutputFilter DEFLATE js css

    #The following line also enables compression by file content type, for the following list of Content-Type:s
    AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml

    #The following lines are to avoid bugs with some browsers
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html 
</IfModule>

这里是如何添加Vary Accept-Encoding头部的方法:[src]

<IfModule mod_headers.c>
  <FilesMatch "\.(js|css|xml|gz)$">
    Header append Vary: Accept-Encoding
  </FilesMatch>
</IfModule>

Vary:头部告诉服务器,该URL返回的内容将根据某个请求标头的值而变化。在这里,它表示会为那些发送 Accept-Encoding: gzip, deflate 标头的客户端提供不同的内容,而对于没有发送此标头的客户端则提供其他内容。我所知道的主要优点是让中间缓存代理知道它们需要针对此更改为同一URL维护两个不同版本。


3
我认为mod_deflate默认情况下应该发送Vary头部。 - Matthew Flaschen
3
Apache 2.2版本不需要上文中提到的mod_headers模块,已经包含了你需要的功能,可以使用mod_deflate模块代替。 http://httpd.apache.org/docs/2.2/mod/mod_deflate.html - Ari Maniatis
代理缓存服务器应始终存储文件的未压缩和压缩版本,因为某些客户端不接受GZip压缩文件。但是,除非有Vary:Accept-Encoding头,否则很多客户端都不会接受压缩文件,因此我们将使用mod_headers确保发送一个。 - Chaoley
一些公共代理存在缺陷,无法检测到Content-Encoding响应头的存在。这可能导致压缩版本被传递到无法正确解压文件的客户端浏览器中。 设置Vary: Accept-Encoding响应头。这将指示代理缓存两个版本的资源:一个压缩的,一个未压缩的。根据客户端请求头交付资源的正确版本。- https://developers.google.com/speed/docs/best-practices/caching - Chaoley
我也从PageSpeed得到了这个建议,我只使用了上面第二段代码:<IfModule mod_headers.c>...然后它就像魔法一样奏效了。请注意:我首先在我的cpanel中启用了gzip压缩...谢谢。 - Sarah
显示剩余4条评论

4
我担心Aularon没有提供足够的步骤来完成这个过程。经过一些试错,我成功地在我的专用WHM服务器上启用了Gzipping。
以下是步骤:
1. 在WHM中运行EasyApache,在详尽选项列表中选择Deflate,然后重新构建服务器。 2. 完成后,前往服务配置>>Apache配置>>包含编辑器>>虚拟主机后,选择所有版本,然后将mod_headers.c和mod_headers.c代码(在Aularon的帖子中列出)粘贴到输入字段的顶部。 3. 保存后,平均看到75.36%的数据节省!您可以使用此HTTP压缩工具运行Before和After测试,以查看自己的结果:http://www.whatsmyip.org/http_compression/ 希望这对大家有用!
- Matt

3
要将字体文件也压缩为gzip格式!
add "x-font/otf x-font/ttf x-font/eot"

就像这样:

AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml x-font/otf x-font/ttf x-font/eot

1

如果有人需要用于 NGINX 配置文件的代码段,这里是示例:

location ~* \.(js|css|xml|gz)$ {
    add_header Vary "Accept-Encoding";
    (... other headers or rules ...)
}

1
很多时间都花费在澄清那个问题上。请阅读this post以获取高级.HTACCESS代码,并了解它们的作用。
你可以使用:
Header append Vary "Accept-Encoding"
#or
Header set Vary "Accept-Encoding"

1
这让我疯狂了,但似乎aularon的编辑在"Vary"后面缺少了冒号。所以将"Vary Accept-Encoding"更改为"Vary: Accept-Encoding"解决了我的问题。
我本来想在帖子下面发表评论的,但似乎不允许我这样做。
无论如何,我希望这能帮助其他人避免我曾经遇到的麻烦。

2
你确定这会有所不同吗?在2.2文档中,没有一个例子包括冒号:http://httpd.apache.org/docs/2.2/mod/mod_headers.html - Nic Cottrell

0

无需指定或检查文件是否已压缩,您可以将其发送到每个文件,每个请求都可以。

它告诉下游代理如何匹配未来的请求头以决定是否可以使用缓存响应而不是从源服务器请求新的响应。

<ifModule mod_headers.c>
  Header unset Vary
  Header set Vary "Accept-Encoding, X-HTTP-Method-Override, X-Forwarded-For, Remote-Address, X-Real-IP, X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Server"
</ifModule>
  • unset 是为了修复一些旧版 GoDaddy 托管中的错误,可选。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接