如何设置HTTP头(用于缓存控制)?

273

如何为我的网站启用浏览器缓存?我只需像这样在头部中放置cache-control:public吗?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
Cache-Control:public;
>

我正在使用最新版本的 XAMPP 开发 PHP。


你使用哪种服务器端语言?PHP?ASP?JSP?设置头部的方式相似但并不完全相同。或者如果你正在缓存图像...通常这是在你的Apache(或Web服务器)配置中完成的。 - scunliffe
遗憾的是,那个“解决方案”只会生成一个无效的DOCTYPE ;-) 如果你想从HTML中实现它(我不建议这样做),你可以使用META HTTP-EQUIV - user166390
8个回答

236

要在HTML中使用缓存控制,可以使用meta标签,例如:

<meta http-equiv="Cache-control" content="public">

内容字段中的值被定义为以下四个值之一。

Cache-Control头的一些信息如下所示:

HTTP 1.1。允许的值 = PUBLIC | PRIVATE | NO-CACHE | NO-STORE。

Public - 可以在公共共享缓存中缓存。
Private - 只能在私人缓存中缓存。
No-Cache - 不能被缓存。
No-Store - 可以被缓存但不会被存档。

CACHE-CONTROL:NO-CACHE 指令表示不应使用缓存的信息,而应将请求转发到源服务器。此指令的语义与 PRAGMA:NO-CACHE 相同。

当向未知是否符合 HTTP/1.1 标准的服务器发送 no-cache 请求时,客户端应该包括 PRAGMA: NO-CACHE 和 CACHE-CONTROL: NO-CACHE。还请参见 EXPIRES。

注意:最好在 HTTP 中指定缓存命令,而不是在 META 语句中,在那里它们可能会影响更多的是代理和其他可能缓存信息的中间件,而不仅仅是浏览器。


51
HTML5禁止这样做,并且<meta>一直以来都是指定缓存的一种糟糕而不稳定的方式。 - Kornel
3
我有困难理解你链接的哪一部分禁止了回答的哪一部分……元标记规范并没有关于不喜欢这里写的内容或禁止它的规定吗? - Félix Adriyel Gagnon-Grenier
1
"@FélixGagnon-Grenier "http-equiv"属性是一个枚举属性,这意味着它只允许规范表格中的值。在后面的部分中,它甚至提到了缓存(“其他Pragma指令”):>与影响HTTP处理模型的标头相对应的Pragma指令(例如缓存)不得注册,因为它们会导致实现HTML的用户代理和不实现HTML的用户代理之间的HTTP级别行为不同。" - Kornel
这个内容只限于上面定义的四个值吗?那no-transform, max-age, s-maxage, must-revalidate, proxy-revalidate又怎么样?我们可以使用它们吗? - Ram Patra
7
引用的文件在“不存储”(no-store)值方面并不正确(尽管该文件本身引用了RFC 2068)。 "不存储"可以完全防止文档被存储/缓存,而“不缓存”(no-cache)则允许将其存储,但必须每次与服务器进行检查。 浏览器倾向于存储“不缓存”页面以启用后退功能等。 - MrWhite
5
谷歌为 HTTP 缓存提供了易于参考的指南,IMO 这是最简单的方式之一:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en#cache-control。 - MrWhite

150

您可以使用以下方式在PHP中设置标头

<?php
  //set headers to NOT cache a page
  header("Cache-Control: no-cache, must-revalidate"); //HTTP 1.1
  header("Pragma: no-cache"); //HTTP 1.0
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past

  //or, if you DO want a file to cache, use:
  header("Cache-Control: max-age=2592000"); //30days (60sec * 60min * 24hours * 30days)

?>

注意,实际使用的标头取决于您的需求(以及是否需要支持HTTP 1.0和/或HTTP 1.1)。

4
对于绝大多数浏览器来说,PragmaExpires头部可能是多余的。 - thijsai
2
@thijsai 是的,HTTP/1.0 也已经过时了...根据您的用户矩阵仅使用您需要的标头。 - scunliffe
为了更好地理解缓存控制,请参阅https://csswizardry.com/2019/03/cache-control-for-civilians/。 - Teenage

72

正如我所写的,最好使用.htaccess文件进行控制缓存,但要注意缓存内容的保留时间。

使用:

<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>

其中: 604800 = 7天

PS: 这可以用来重置任何标头(header)


8
如果您可以访问您的Web服务器配置文件,可以将这些内容放置在那里而不是在.htaccess中。有一个误解认为您必须将某些内容放在Apache的.htaccess文件中,并且一直以来都会得到像这样的答案。除非您无法直接访问Web服务器配置(例如在多个虚拟主机环境中),否则您不需要任何.htaccess文件。也许只需写Web服务器配置文件或.htaccess文件即可。请参见https://www.danielmorell.com/guides/htaccess-seo/basics/dont-use-htaccess-unless-you-must - Sybille Peters
1
另外,您可能需要添加 mod_headers(或将其包含在 <IfModule> 中)。 - Sybille Peters

36

该页面(http://www.askapache.com/htaccess/apache-speed-cache-control.html)建议使用以下代码:

添加缓存控制头信息

将以下代码加入你的根目录.htaccess文件中,但如果你可以访问httpd.conf则最好在其中进行修改。

此代码使用FilesMatch指令和Header指令将缓存控制头信息添加到特定的文件中。

# 480 weeks
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=290304000, public"
</FilesMatch>

3
这非常重要吗?"max-age=290304000, public" 或者 "public, max-age=290304000",两种方式都正确吗? - Satya Prakash
2
如果值不冲突(如cacheno-cache),则顺序无关紧要。 max-agepublic 不冲突,因此顺序无关紧要。 - Blaise
3
请注意,由于它使用了“Header”指令,您必须启用“mod_headers”。 - Skippy le Grand Gourou
@Skippy le Grand Gourou,我该如何启用mod_headers? - Sam
@SamuelStratford 我了解在其他发行版上可能会有所不同,但在Debian下,您可以使用a2enmod或将符号链接从/etc/apache2/mods-available/headers.load创建到/etc/apache2/mods-enabled/headers.load - Skippy le Grand Gourou

31

这是我在实际网站中使用过的最佳.htaccess文件:

<ifModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

##Tweaks##
Header set X-Frame-Options SAMEORIGIN

## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>
## EXPIRES CACHING ##

<IfModule mod_headers.c>
    Header set Connection keep-alive
    <filesmatch "\.(ico|flv|gif|swf|eot|woff|otf|ttf|svg)$">
        Header set Cache-Control "max-age=2592000, public"
    </filesmatch>
    <filesmatch "\.(jpg|jpeg|png)$">
        Header set Cache-Control "max-age=1209600, public"
    </filesmatch>
    # css and js should use private for proxy caching https://developers.google.com/speed/docs/best-practices/caching#LeverageProxyCaching
    <filesmatch "\.(css)$">
        Header set Cache-Control "max-age=31536000, private"
    </filesmatch>
    <filesmatch "\.(js)$">
        Header set Cache-Control "max-age=1209600, private"
    </filesmatch>
    <filesMatch "\.(x?html?|php)$">
        Header set Cache-Control "max-age=600, private, must-revalidate"
      </filesMatch>
</IfModule>

4
一个近乎完美的 .htaccess 文件示例......如果指定图片并说明如何编写图片路径以及将 .htaccess 文件放在哪里(例如,图像目录或索引目录中),那就更完整了。例如 '<IfModule mod_headers.c> <Files /img/myimage.jpg> Header append Cache-Control "max-age=3600, must-revalidate" </Files></IfModule>' 是否可行?还是将其粘贴到 img 目录下的 '<filesmatch "^(example.jpg|sample.png)$">Header set Cache-Control "max-age=31536000, public"</filesmatch>'... 在所有情况下都使用相同的策略似乎很危险-无论如何,如果可能提供具体示例将是很好的。 - Marco-UandL
2
仅供参考:在JS和CSS文件上使用gzip压缩可能会破坏您的SSL加密。如果您依赖安全性,请勿打开gzip。 - Eduard Void
1
这是缓存登录账户页面,所以您无法从您的账户中注销。更糟糕的是,其他人不能仅仅访问账户页面并使用上一个用户的登录信息登录。在电子商务网站上不建议使用此功能,您应该删除 <filesMatch "\.(x?html?|php)$"> 以避免静态HTML页面被缓存。其余的文件匹配是可以的。 - nicoX
1
您已经复制了 <FilesMatch "\.(eot|woff|otf|ttf|svg)$"> - nicoX
2
如果您使用代理缓存,可以将cssjs设置为私有。我在您提供的链接中没有找到任何关于此的建议。大多数CDN都建议您缓存这些值。 - nicoX

17

对于 Apache 服务器,您可以检查 mod_expires 设置 Expires 和 Cache-Control 头文件。

另外,您也可以使用 Header 指令自己添加 Cache-Control:

Header set Cache-Control "max-age=290304000, public"

6
缓存控制标签允许Web发布者定义页面应如何被缓存处理。它们包括指令来声明哪些内容可以缓存,哪些可以由缓存存储,修改到期机制,以及重新验证和重载控件。

允许的值包括:

Public - 可以在公共共享缓存中缓存
Private - 只能在私有缓存中缓存
no-Cache - 不能被缓存
no-Store - 可以被缓存但不会被归档

请注意大小写敏感性。在您的网页源代码中添加以下meta标签。标签末尾的拼写差异是您使用“/> = xml”还是“> = html。”

    <meta http-equiv="Cache-control" content="public">
    <meta http-equiv="Cache-control" content="private">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache-control" content="no-store">

Source-> MetaTags


1
更正:no-store 不应被缓存,no-cache 也不允许被缓存,但在保留之前必须与服务器进行检查 - 参见 http://palizine.plynt.com/issues/2008Jul/cache-control-attributes/。 - DangerMouse
Cache-Control no-store - no-store与no-cache类似,因为响应不能被缓存和重复使用,但是有一个重要的区别。no-store要求每次从源服务器请求和下载资源。在处理私人信息时,这是一个重要的特性。 - MarcoZen

4

OWASP推荐以下做法:

尽可能地确保设置cache-control HTTP头,其中包含no-cache、no-store、must-revalidate、private;并且设置pragma HTTP头,其中包含no-cache。

<IfModule mod_headers.c>
    Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
    Header set Pragma "no-cache"
</IfModule>

1
你能添加一个链接吗?此外,这不取决于内容类型吗?为什么总是设置no-store?为什么要私有?只有对于私有页面才有意义。 - Sybille Peters
“Pragma”头部真的很老(HTTP/1.0),所以我怀疑这是旧建议。 - Colin 't Hart

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