Ok, here's a tough one:
I have these website with several CSS files that uses cache busting and it worked fine. i was getting 403 Not Modified with every call.
But now Im using this rule in my htaccess to concatenate all my files
<FilesMatch "\.combined\.css$">
Options +Includes
AddOutputFilterByType INCLUDES text/css
SetOutputFilter INCLUDES
</FilesMatch>
Inside script.combined.css you can find this:
<!--#include file="file1.css" -->
<!--#include file="file2.css" -->
The problem comes that even though my file "script.combined.css" uses cache busting. it's always returning "200 Ok". These are the headers of script.combined.css:
Request
URL:http://XXX/css/script.combined.css
Request Method:GET
Status Code:200 OK
Request Headers
Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:typo3-login-cookiecheck=true; PHPSESSID=2evc53ngjjobateti38gpahtt7; tx_phpmyadmin=quf4sgevagubd1snd9eoq4g4d0; be_typo_user=0f4c7e291b6d7673310d6f15da687910; Typo3InstallTool=62erpih8fmqbbl3pe75pcenuu0; fe_typo_user=a7e5de71521603161fa598ed523b024b
Host:XXX
Referer:http://XXX/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30
Response Headers
Accept-Ranges:bytes
Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Content-Type:text/css
Date:Wed, 17 Aug 2011 13:56:42 GMT
Expires:Thu, 16 Aug 2012 13:56:42 GMT
Keep-Alive:timeout=5, max=99
Server:HTTPD
Transfer-Encoding:chunked
...while these are the headers for another simple css file:
Request URL:http://XXX/css/style.css
Request Method:GET
Status Code:304 Not Modified
Request Headers
Accept:text/css,*/*;q=0.1
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:typo3-login-cookiecheck=true; PHPSESSID=2evc53ngjjobateti38gpahtt7; tx_phpmyadmin=quf4sgevagubd1snd9eoq4g4d0; be_typo_user=0f4c7e291b6d7673310d6f15da687910; Typo3InstallTool=62erpih8fmqbbl3pe75pcenuu0; fe_typo_user=a7e5de71521603161fa598ed523b024b
Host:XXX
If-Modified-Since:Wed, 17 Aug 2011 11:45:17 GMT
Referer:http://XXX/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30
Response Headers
Cache-Control:max-age=31536000, public
Connection:Keep-Alive
Date:Wed, 17 Aug 2011 13:56:42 GMT
Expires:Thu, 16 Aug 2012 13:56:42 GMT
Keep-Alive:timeout=5, max=97
Server:HTTPD
I used an extension to measure Page Speed from google and I got this message:
Specify a cache validator
The following resources are missing a cache validator. Resources that
do not specify a cache validator cannot be refreshed efficiently.
Specify a Last-Modified or ETag header to enable cache validation for
the following resources:
http://XXX/css/script.combined.css?1313583214
What should I do??
According to Apache's documentation for server side includes:
In its default configuration, Apache does not send the last modified date or content length HTTP headers on SSI pages, because these values are difficult to calculate for dynamic content.
http://httpd.apache.org/docs/1.3/howto/ssi.html
So a direct request in your browser to styles.combined.css will never return a 304 Not Modified status.
But if you're setting expires headers, the browser simply pulls the asset from the local cache. The request to check the last-modified date is unnecessary and doesn't get sent.
I suggest you take a look at the fine work of the html5 boilerplate project which gives you a nice base to start of with in new projects. But more importantly it includes a pimped out .htaccess file with well commented rules.
The following snippet might be of use to you specifically:
# ----------------------------------------------------------------------
# Expires headers (for better cache control)
# ----------------------------------------------------------------------
# These are pretty far-future expires headers.
# They assume you control versioning with cachebusting query params like
# <script src="application.js?20100608">
# Additionally, consider that outdated proxies may miscache
# www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/
# If you don't use filenames to version, lower the CSS and JS to something like
# "access plus 1 week" or so.
<IfModule mod_expires.c>
ExpiresActive on
# Perhaps better to whitelist expires rules? Perhaps.
ExpiresDefault "access plus 1 month"
# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Your document html
ExpiresByType text/html "access plus 0 seconds"
# Data
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
# Feed
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/atom+xml "access plus 1 hour"
# Favicon (cannot be renamed)
ExpiresByType image/x-icon "access plus 1 week"
# Media: images, video, audio
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
# HTC files (css3pie)
ExpiresByType text/x-component "access plus 1 month"
# Webfonts
ExpiresByType font/truetype "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
# CSS and JavaScript
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
<IfModule mod_headers.c>
Header append Cache-Control "public"
</IfModule>
</IfModule>
# ----------------------------------------------------------------------
# ETag removal
# ----------------------------------------------------------------------
# FileETag None is not enough for every server.
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
# Since we're sending far-future expires, we don't need ETags for
# static content.
# developer.yahoo.com/performance/rules.html#etags
FileETag None
Related
Will Cloudfront cache a dynamic response or will it only cache if it's a physical file on the server? I'm thinking maybe that's why it doesn't cache our sitemap.xml response.
The Cloudfront CDN works fine for our images, css, and js, but not this sitemap.xml request, even with it's own behavior in the Cloudfront distribution.
Stack: Cloudfront, WordPress, Apache, and the sitemap plugin is called XML Sitemap & Google News.
There is no static or physical sitemap.xml file. The plugin generates the response on-the-fly when requested. We want to cache it for 15 mins.
.htaccess looks like this. The cache expires after 900 seconds or 15 minutes.
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType text/cache-manifest "access plus 0 seconds"
ExpiresByType text/html "access plus 0 seconds"
# Data
ExpiresByType text/xml "access plus 15 minutes"
ExpiresByType application/xml "access plus 15 minutes"
ExpiresByType application/json "access plus 15 minutes"
# Feed
ExpiresByType application/rss+xml "access plus 15 minutes"
ExpiresByType application/atom+xml "access plus 15 minutes"
Cloudfront behavior is set to 600 seconds or 10 mins. I've tried using the headers on the origin as well, no joy.
I've received information from a customer that their website visitors don't get the latest version of their Wordpress website. I tracked it down to browser caching. The max-age is set to 6 months. And this setting is default behaviour by the SiteGround caching plugin. After installing the SG Optimizer caching plugin the below code is added to the htaccess file. This sets the max-age and expiry to a date six months from now. As you can see it also caches html locally. This is the code that gets added to the htaccess:
# HTTPS forced by SG-Optimizer
<IfModule mod_rewrite.c>
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# END HTTPS
# Leverage Browser Caching by SG-Optimizer
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 6 months"
# CSS
ExpiresByType text/css "access plus 1 year"
# HTML components (HTCs)
ExpiresByType text/x-component "access plus 2 months"
# HTML
ExpiresByType text/html "access plus 6 months"
# JavaScript
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
# Manifest files
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Media
ExpiresByType audio/ogg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/ogg "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType application/pdf "access plus 1 year"
ExpiresByType application/x-shockwave-flash "access plus 1 year"
# Web feeds
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
# Web fonts
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType application/x-font-ttf "access plus 1 year"
ExpiresByType font/opentype "access plus 1 year"
</IfModule>
# END LBC
# GZIP enabled by SG-Optimizer
<IfModule mod_deflate.c>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
</IfModule>
</IfModule>
# END GZIP
I've tried fixing it by removing above lines from .htaccess and adding lines like the following:
# DISABLE CACHING
<IfModule mod_expires.c>
ExpiresActive Off
</IfModule>
<IfModule mod_headers.c>
FileETag None
Header unset ETag
Header unset Pragma
Header unset Cache-Control
Header unset Last-Modified
Header set Pragma "no-cache"
Header Set Cache-Control "max-age=0, public, must-revalidate"
Header Set Expires "Thu, 1 Jan 1970 00:00:00 GMT"
</IfModule>
But it does not help. It seems the browser just does not make any requests to the server anymore since it has it locally cached an it is serving everything from local cache to the user until the max-age of 6 months are over. Then it will check for a newer version. This problem occurs on all our websites that we host and created for our customers, so this is a big issue for us.
I've already tried changing site url to one without www. Tried to switch the homepage to another page, did not work either. Maybe moving to entire site to a new ip and changing the a-record would work to override local cache?
I'm looking for a clever way to fix this problem. I hope someone knows a solution.
Many thanks in advance!
Yah, that is a problem every CDN has run into and invalidating downstream caches is difficult. There are two possible solutions.
Alter the name of the resource, this can be done automatically with Pagespeed if you have control of the server. See the cache extend filter.
Alternatively, inline the image in the HTML using a dataurl per RFC 2397. Easier read is this post by Phil Whelan.
When i pasted this code into my .htaccess file, everything works fine on my desktop version.
# Optimize cache-control
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault “access plus 1 month”
ExpiresByType image/gif “access plus 1 month”
ExpiresByType image/png “access plus 1 month”
ExpiresByType image/jpg “access plus 1 month”
ExpiresByType image/jpeg “access plus 1 month”
ExpiresByType text/html “access plus 3 days”
ExpiresByType text/xml “access plus 1 seconds”
ExpiresByType text/plain “access plus 1 seconds”
ExpiresByType application/xml “access plus 1 seconds”
ExpiresByType application/rss+xml “access plus 1 seconds”
ExpiresByType application/json “access plus 1 seconds”
ExpiresByType text/css “access plus 1 week”
ExpiresByType text/javascript “access plus 1 week”
ExpiresByType application/javascript “access plus 1 week”
ExpiresByType application/x-javascript “access plus 1 week”
ExpiresByType image/x-ico “access plus 1 year”
ExpiresByType image/x-icon “access plus 1 year”
ExpiresByType application/pdf “access plus 1 month”
<IfModule mod_headers.c>
Header unset ETag
Header unset Pragma
Header unset Last-Modified
Header append Cache-Control “public, no-transform, must-revalidate”
Header set Last-modified “Mon, 1 Oct 2018 10:10:10 GMT”
</IfModule>
</IfModule>
On another hand for mobile I have 500 error.
Internal Server Error The server encountered an internal error or
misconfiguration and was unable to complete your request.
Please contact the server administrator at
webmaster to inform them of the time this error
occurred, and the actions you performed just before this error.
More information about this error may be available in the server error
log.
Additionally, a 500 Internal Server Error error was encountered while
trying to use an ErrorDocument to handle the request.
I am failing the Google and GTmetrix speed tests miserably for my WordPress site. Both specify that browser caching is not enabled.
I have tried a few caching plugins, such as WP Super Cache, but they have had zero effect.
I have also manually edited the .htaccess file with the following:
##### EXPIRE CACHING - LEVERAGE BROWSER CACHING #####
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month 1 days"
ExpiresByType text/html "access plus 1 month 1 days"
ExpiresByType image/gif "access plus 1 month 1 days"
ExpiresByType image/jpeg "access plus 1 month 1 days"
ExpiresByType image/png "access plus 1 month 1 days"
ExpiresByType text/css "access plus 1 month 1 days"
ExpiresByType text/javascript "access plus 1 month 1 week"
ExpiresByType application/x-javascript "access plus 1 month 1 days"
ExpiresByType text/xml "access plus 1 seconds"
</IfModule>
##### END EXPIRE CACHING #####
But, again, it has had zero impact. I have tried my host provider, BlueHost, three times and they have given me a different response each time but they all roughly equate to "nothing to do with us."
Does anyone have an idea what I may be doing wrong?
I feel like I am hitting my head against a brick wall with this one!
I would appreciate any help you can give me.
I was having the same issue with WP Super Cache (which is how I found this thread). I switched to WP Fastest Cache which solved it for me (it has it as a toggle setting in the options) - thought I'd post just in case you hadn't fixed it yet.
The code that you have added will work only when apache module mod_expires is active.
Alternatively, you can use the following code (add it to .htaccess)
# 1 YEAR
<FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
# 1 WEEK
<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>
# 1 WEEK
<FilesMatch "\.(txt|xml|js|css)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
# NEVER CACHE - notice the extra directives
<FilesMatch "\.(html|htm|php|cgi|pl)$">
Header set Cache-Control "max-age=0, private, no-store, no-cache, must-revalidate"
</FilesMatch>
Please note, that this will leverage browser caching only for internal files, you can't control it for external files.
I´ve been trying to get The leverage browser cache for quite a while and I have no idea what could be the problem. I tried several methods to activate it, but nothing works...
The site is running on Namecheap Hosting. I already contacted the support and asked if the mod_expires module is active and according to the customer support it is...
This is the code I´ve been using:
# START --- Browser Cache Control
# Turn on Expires and set default to 0
ExpiresActive On
ExpiresDefault A0
# Set up caching on media files for 1 year (forever?)
<FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav)$">
ExpiresDefault A29030400
Header append Cache-Control "public"
</FilesMatch>
# Set up caching on media files for 1 week
<FilesMatch "\.(gif|jpg|jpeg|png|swf)$">
ExpiresDefault A604800
Header append Cache-Control "public"
</FilesMatch>
# Set up 2 Hour caching on commonly updated files
<FilesMatch "\.(xml|txt|html|js|css)$">
ExpiresDefault A7200
Header append Cache-Control "proxy-revalidate"
</FilesMatch>
# Force no caching for dynamic files
<FilesMatch "\.(php|cgi|pl|htm)$">
ExpiresActive Off
Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
Header set Pragma "no-cache"
</FilesMatch>
# END --- Browser Cache Control
I already tried some other methods like:
## 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 ##
It would be really nice if anyone has an idea what could be wrong with my code ;)
I HAVE RESOLVED IT
In short:-
I just resolved this issue but you have to enable expires_module module. For linux you can do it easy like that.
azureuser#azure: sudo a2enmod expires
Enabling module expires.
To activate the new configuration, you need to run:
service apache2 restart
azureuser#azure: sudo service apache2 restart
[....] Restarting web server:
. ok
In Deep:-
People are seeing that among other things they need to Leverage Browser Caching, so they do what they think is the one stop fix and thats to add something like the following to their .htaccess file:
ExpiresActive On
ExpiresDefault "access plus 5 seconds"
ExpiresByType image/x-icon "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType text/javascript "access plus 216000 seconds"
ExpiresByType application/javascript "access plus 216000 seconds"
ExpiresByType application/x-javascript "access plus 216000 seconds"
ExpiresByType text/html "access plus 600 seconds"
ExpiresByType application/xhtml+xml "access plus 600 seconds"
This seems all well and good but they then go back to their metrics tool, re-analyse and see that this issue is still prevalent.. They then spend the next while trying to figure out why this is not working and their website is still in the dog house metrics wise. well fear not the issue is not a website one so to speak, its a server one. If you are using a Debian server this is the quick fix you have been looking for: log into your Dedicated/VPS and issue the following command which will check to see what modules are loaded on your server, you are looking for the expires_module in the list
azureuser#azure: sudo apachectl -M
Loaded Modules:
core_module (static)
log_config_module (static)
logio_module (static)
version_module (static)
mpm_prefork_module (static)
http_module (static)
so_module (static)
alias_module (shared)
auth_basic_module (shared)
authn_file_module (shared)
authz_default_module (shared)
authz_groupfile_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
cgi_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
mime_module (shared)
negotiation_module (shared)
php5_module (shared)
reqtimeout_module (shared)
rewrite_module (shared)
setenvif_module (shared)
ssl_module (shared)
status_module (shared)
Syntax OK
So there is no sign of the expires_module in this list, next up all you have to do is install it
azureuser#azure: sudo a2enmod expires
Enabling module expires.
To activate the new configuration, you need to run:
service apache2 restart
azureuser#azure: sudo service apache2 restart
[....] Restarting web server:
. ok
Head back to your metrics and rerun the test, be sure to add the code specified above to your htaccess also. You should now have passed the Leverage browser Caching test.
My website speed was 85, I was trying to resolve Leverage cache but finally i resolved it with this.
Screenshot:- https://prnt.sc/iu3z2t