45

I am trying to create a htaccess file for my website and the pageSpeed insights has shown that there are images and one css file without expiration.

I am not sure where to start with this or how to do it, I have this code from a tutorial online and was wondering if this would be enough to work.

<IfModule mod_expires.c>
ExpiresActive On
############################################
## Add default Expires header
## http://developer.yahoo.com/performance/rules.html#expires
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
ExpiresDefault "access plus 1 year"
</FilesMatch>
</IfModule>

Or does this code do what I need it to do?

Thanks

NullPoiиteя
  • 56,591
  • 22
  • 125
  • 143
Sam
  • 1,207
  • 4
  • 26
  • 50

4 Answers4

66

try something like

<IfModule mod_expires.c> 
  ExpiresActive On
  ExpiresDefault "access plus 1 seconds"
  ExpiresByType text/html "access plus 1 seconds"
  ExpiresByType image/x-icon "access plus 2592000 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 86400 seconds"
  ExpiresByType application/x-javascript "access plus 86400 seconds"
</IfModule>

or

<FilesMatch "\.(?i:gif|jpe?g|png|ico|css|js|swf)$">

  <IfModule mod_headers.c>
    Header set Cache-Control "max-age=172800, public, must-revalidate"
  </IfModule>

</FilesMatch>
NullPoiиteя
  • 56,591
  • 22
  • 125
  • 143
  • Thanks, would I add this in between the tags as I tried this and it still shows as expiration not set – Sam Oct 23 '12 at 11:06
  • 1
    dont add this in `` you could add this before or after this – NullPoiиteя Oct 23 '12 at 11:07
  • I have added in the code you have given above which is 'ExpiresActive On to ExpiresByType application/x-javascript "access plus 86400 seconds"' that's all I have in the .htaccess file and it's not working, please can you help. thanks – Sam Oct 23 '12 at 11:23
  • is your expiry module on in Apache – NullPoiиteя Oct 23 '12 at 11:26
  • Im adding the file in the webspace the directory of my webpage, is there something I need to configure? – Sam Oct 23 '12 at 11:39
  • @Ricky have you add this LoadModule expires_module modules/mod_expires.so and LoadModule cache_module modules/mod_cache.so in httpd.conf file – NullPoiиteя Oct 23 '12 at 11:42
  • thanks, I'm not sure where this file is, but have noticed there is another .htaccess file in the logs directory is this the one I should be using? – Sam Oct 23 '12 at 11:53
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18466/discussion-between-nullpointer-and-ricky) – NullPoiиteя Oct 23 '12 at 11:54
  • I have put the code given in chat into the .htaccess file I added to the root directory but still says the same. I have left the .htaccess file in the parent directory the same as it was as it's read only anyway. Thanks for your help. – Sam Oct 23 '12 at 13:47
  • @NullPoiиteяღ - +1 - I think you should change `` to `` – Sina R. Nov 07 '13 at 17:07
  • The general suggestion is to wait 15 minutes after making the change to the .htaccess file for the changes to take affect. – Matty J Nov 17 '13 at 23:12
  • Don't forget that `GIF` and `Gif` are valid too.. make it insensitive match: `` :) –  Jan 19 '16 at 11:20
35

I know this is a belated answer, but the above didn't work for me. Instead I used the following:

<FilesMatch "\.(ico|pdf|jpg|jpeg|png|webp|gif|html|htm|xml|txt|xsl|css)$">
Header set Cache-Control "max-age=31536050"
</FilesMatch>
Matthew Johnson
  • 4,875
  • 2
  • 38
  • 51
  • @MatthewJohnson How is is different from the first answer? :/ – Raja Khoury Apr 21 '15 at 21:22
  • 3
    @AwRak It caches more file types is one difference. The other is that the Cache-Control doesn't have the "public, must-revalidate". The "must-revalidate" is explained better [here](http://stackoverflow.com/a/8729854/1902882) Public/private info can be found [here](http://stackoverflow.com/a/3343849/1902882). Sorry, but that's about the extent of my knowledge on that! – Matthew Johnson Apr 22 '15 at 01:41
  • Both Pingdom and Google Page Insights expect CSS files to be cached. Might be good to add it to this answer, especially since it was part of the OP's original question. – clayRay Mar 04 '19 at 01:38
  • 1
    @clayRay Added, thanks! I'm not going to update much else, but it should be noted that changes to the CSS file would then require some sort of cache busting. – Matthew Johnson Mar 07 '19 at 20:34
20

Above answer is working for me but, I also want to add other files extension in .htaccess. Below code give me a good solution.

Full .htaccess code to pass on Google PageSpeed Insight:

  1. Enable compression
  2. Leverage browser caching
# 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>

There is also some configurations for various web servers see here.
Hope this would help to get the 100/100 score.

Sahil Patel
  • 1,570
  • 2
  • 15
  • 34
2

Regarding Matthew Johnson"s answer above, as-is it didn't work for me on my Laravel5.2 website But I added 'php' to the list and it worked!! Thank you Matthew Johnson

<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif|html|htm|xml|php|txt|xsl)$">
Header set Cache-Control "max-age=31536050"
</FilesMatch>
Vasko
  • 257
  • 3
  • 13
  • Given that this sets caching for browsers, why would you add a server-side script type such as PHP to the list? – clayRay Mar 04 '19 at 01:18
  • There could be edge cases where files are being served through a php script so while odd, this does make sense for some. – MLK.DEV May 20 '19 at 13:25