利用浏览器缓存,在apache或.htaccess上如何实现?

56

我该怎么做?我有一个巨大的文件列表,Google Speed Page说要“利用浏览器缓存”..但是我不知道该怎么办?我需要修改Apache配置文件(如下)还是在我的.htaccess页面中添加一些内容?

 <IfModule mod_proxy.c>
        ProxyRequests Off
        CacheRoot "/var/run/proxy"
        CacheSize 1024
        CacheGcInterval 24
    #CacheMaxExpire 24
    #CacheLastModifiedFactor 0.1
    #CacheDefaultExpire 1
    #NoCache a_domain.com another_domain.edu joes.garage_sale.com
        <Directory "disabled_proxy">
            Allow from example.com
            Deny from all
            Order Deny,Allow
        </Directory>
    </IfModule>
    ##
    #### mod_expires is configured so that all static files but images
    #### expire after 60 seconds. Any response that has a life span of more
    #### than 5 seconds (see webperfcache.conf) will be cached by webperfcache.
    #### Make sure your CGIs return a "Cache-Control: no-cache" header if you
    #### elect to make your dynamically generated HTML pages not cache-able.
    #### If all your HTML pages are static you may also increase ExpiresDefault.

    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresDefault A60
        ExpiresByType image/bmp A3600
        ExpiresByType image/gif A3600
        ExpiresByType image/ief A3600
        ExpiresByType image/jpeg A3600
        ExpiresByType image/png A3600
        ExpiresByType image/tiff A3600
        ExpiresByType image/x-cmu-raster A3600
        ExpiresByType image/x-portable-anymap A3600
        ExpiresByType image/x-portable-bitmap A3600
        ExpiresByType image/x-portable-graymap A3600
        ExpiresByType image/x-portable-pixmap A3600
        ExpiresByType image/x-rgb  A3600
        ExpiresByType image/x-xbitmap A3600
        ExpiresByType image/x-xpixmap A3600
        ExpiresByType image/x-xwindowdump A3600
        ExpiresByType audio/basic A3600
        ExpiresByType audio/midi A3600
        ExpiresByType audio/mpeg A3600
        ExpiresByType audio/x-aiff A3600
        ExpiresByType audio/x-pn-realaudio A3600
        ExpiresByType audio/x-pn-realaudio-plugin A3600
        ExpiresByType audio/x-realaudio A3600
        ExpiresByType audio/x-wav A3600
        ExpiresByType video/mpeg A3600
        ExpiresByType video/quicktime A3600
        ExpiresByType video/x-msvideo A3600
        ExpiresByType video/x-sgi-movie A3600
    </IfModule>
4个回答

102

我抓住机会提供完整的.htaccess代码,以便通过Google PageSpeed Insights:

  1. 启用压缩
  2. 利用浏览器缓存
# Enable Compression
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE application/x-font
  AddOutputFilterByType DEFLATE application/x-font-opentype
  AddOutputFilterByType DEFLATE application/x-font-otf
  AddOutputFilterByType DEFLATE application/x-font-truetype
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE font/otf
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE text/plain
</IfModule>
<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>

# Leverage Browser 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>
<IfModule mod_headers.c>
  <filesmatch "\.(ico|flv|jpg|jpeg|png|gif|css|swf)$">
  Header set Cache-Control "max-age=2678400, public"
  </filesmatch>
  <filesmatch "\.(html|htm)$">
  Header set Cache-Control "max-age=7200, private, must-revalidate"
  </filesmatch>
  <filesmatch "\.(pdf)$">
  Header set Cache-Control "max-age=86400, public"
  </filesmatch>
  <filesmatch "\.(js)$">
  Header set Cache-Control "max-age=2678400, private"
  </filesmatch>
</IfModule>
还有一些适用于各种Web服务器的配置,请参阅此处。 希望这能帮助您获得100/100的分数。 优化页面得分

2
我认为mod_headers和mod_expires做的事情是一样的,只是选项不同,应该只使用一个。我有什么遗漏吗? - neelabh
1
感谢@hyip的分享。 - omkara
1
Gtmetrix仍然显示我需要使用你的代码启用gzip压缩。对我来说,这个代码是有效的:AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript - Dexter
1
我原以为100/100只是一个传说!:) 恭喜你。像 opencart 或 woocommerce 这样的许多脚本在 ExpiresDefault 配置方面存在问题。有什么想法吗? - Stavros
任何 ExpiresDefault 都可以被设置 Expires 头字段来覆盖。请观察 .htaccess 层级结构,以确保在更低的层级中不会被覆盖。 - eQ19

46

几天前我也在做同样的事情。 将以下内容添加到我的.htaccess文件中:

ExpiresActive On
ExpiresByType image/gif A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType image/jpg A2592000
ExpiresByType image/png A2592000
ExpiresByType image/x-icon A2592000
ExpiresByType text/css A86400
ExpiresByType text/javascript A86400
ExpiresByType application/x-shockwave-flash A2592000
#
<FilesMatch "\.(gif¦jpe?g¦png¦ico¦css¦js¦swf)$">
Header set Cache-Control "public"
</FilesMatch>

现在当我运行Google速度页面时,利用浏览器缓存不再是一个高优先级的问题。

希望这可以帮到你。


6
请检查您的代码,我在使用您的代码时遇到了内部服务器错误。 - Francesco
2
@Francesco,请检查您的服务器,是否启用了mod_headers.c和mod_expires.c模块? - Dustin Graham
我在CakePHP中遇到了这样的问题,但这并不是所有文件的解决方案:http://stackoverflow.com/questions/18927604/leverage-browser-caching-and-cakephp - SaidbakR
@Adam - 比如说,我设置了 ExpiresByType image/jpg "access 1 year",这意味着在一年内,我的整个网站上的 JPG 图片都将从缓存中加载,对吗?但是如果我更改了任何 JPG 文件,那么它会作为新文件反映在我的网站上吗?还是会在一年内从缓存中加载旧图片? - Helping Hands
@HelpingHands .. 是的,没错。你应该使用"access plus 1 year",你还可以在"Header set Cache-Control"中添加更多设置,以便更好地控制缓存和过期。 - Adam MacDonald

38

以下是我用来控制头信息/缓存的方法,我不是Apache的专家,请告诉我是否有改进的空间,但我知道这个方法在我的所有站点上都运行良好。

Mod_expires

http://httpd.apache.org/docs/2.2/mod/mod_expires.html

该模块可以控制在服务器响应中设置Expires HTTP头和Cache-Control HTTP头的max-age指令。到期日期可以相对于源文件的最后修改时间或客户端访问时间设置。

这些HTTP头是关于文档有效性和持久性的指示,如果缓存,则可能从缓存中获取文档而不是从源获取,直到此时间过去为止。之后,缓存副本被视为“过期”和无效,必须从源获取新副本。

# BEGIN Expires
<ifModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 seconds"
ExpiresByType text/html "access plus 1 seconds"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType text/javascript "access plus 216000 seconds"
ExpiresByType application/x-javascript "access plus 216000 seconds"
</ifModule>
# END Expires

Mod_headers

http://httpd.apache.org/docs/2.2/mod/mod_headers.html

该模块提供了指令来控制和修改HTTP请求和响应头部。可以合并、替换或删除头部。

# BEGIN Caching
<ifModule mod_headers.c>
<filesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$">
Header set Cache-Control "max-age=2592000, public"
</filesMatch>
<filesMatch "\.(css)$">
Header set Cache-Control "max-age=604800, public"
</filesMatch>
<filesMatch "\.(js)$">
Header set Cache-Control "max-age=216000, private"
</filesMatch>
<filesMatch "\.(xml|txt)$">
Header set Cache-Control "max-age=216000, public, must-revalidate"
</filesMatch>
<filesMatch "\.(html|htm|php)$">
Header set Cache-Control "max-age=1, private, must-revalidate"
</filesMatch>
</ifModule>
# END Caching

不要忘记启用 mod_headers 和 mod_expires 模块,您可以通过运行 a2enmod rewritea2enmod headers 命令来实现。 - Tamik Soziev
你为什么在正则表达式中使用双斜杠(\\....)?只使用一个斜杠也是正确的,例如<FilesMatch "\.(gif|jpe?g|png)$">(这个例子直接从FilesMatch文档中复制而来)。 - Quinn Comendant
我不确定为什么我做了@QuinnComendant,感谢你的指正,我已经更新了帖子以反映正确的语法。两种方法都似乎可以正常工作,但保持正确的语法始终是最佳实践。 - Trae Abell

8

首先我们需要检查是否启用了mod_headers.c和mod_expires.c模块。

sudo apache2 -l

如果我们没有它,我们需要启用它们。
sudo a2enmod headers

然后我们需要重新启动apache

sudo apache2 restart

最后,添加.htaccess上的规则(在其他回答中看到的),例如:
ExpiresActive On
ExpiresByType image/gif A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType image/jpg A2592000
ExpiresByType image/png A2592000
ExpiresByType image/x-icon A2592000
ExpiresByType text/css A86400
ExpiresByType text/javascript A86400
ExpiresByType application/x-shockwave-flash A2592000
#
<FilesMatch "\.(gif|jpe?g|png|ico|css|js|swf)$">
Header set Cache-Control "public"
</FilesMatch>

<FilesMatch ".(gif¦jpe?g¦png¦ico¦css¦js¦swf)$"> Header set Cache-Control "public" </FilesMatch> 可能会有错误导致 500 错误。 - matinict

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