how to i add add far-future expires headers to minified cssfiles/scripts? I am using minify to combine css files and javascripts files, but the minified versions don't have a far-future expiration date.
If you're using Apache, then this sort of thing is the way to go. There are several different ways to do it depending on the modules installed; some make it easier than others. I recommend the expires (docs) and headers (docs) modules (they're both required for the example below, but you can pull it off with only headers if you really want).
<LocationMatch "/js/(.*)\.js">
ExpiresDefault "access plus 10 years"
Header set Cache-Control "public"
</LocationMatch>
This example matches all files in /js/ that end with a .js extension and set an expiry time of 10 years into the future relative to the time the file is accessed. It also explicitly sets Cache-Control to be public; we run everything over SSL, so it might not be necessary otherwise, but it won't hurt you either way.
This example can easily be extended to match your CSS locations and files as well; just copy, paste and change the LocationMatch.
There are plenty of sites that will give you a full rundown on this; check out this one, "Caching Tutorial", which seems to cover it all.
/min/README.txt has documentation for sending far-future expires headers.
Minify can send far-future (one year) Expires headers. To enable this you must
add a number to the querystring (e.g. /min/?g=js&1234 or /min/f=file.js&1234)
and alter it whenever a source file is changed. If you have a build process you
can use a build/source control revision number.
You can alternately use the utility function Minify_getUri() to get a "versioned"
Minify URI for use in your HTML.
That depends on what web server you are using. It can't be done by modifying the CSS or script files themselves, though.
Related
I am trying to create a type of font repository for use on my websites, so that I can call to any font in the repository in my css without any other set-up. To do this I created a subdomain on which I placed folders for each font in the repository that contained the various file types for each font. I also placed a css file called font-face.css on the root of the subdomain and filled it with #font-face declarations for each of the fonts, the fonts are linked with an absolute link so that they can be used from anywhere.
My issue is that it seems that I can only use the fonts on that subdomain where they are located, on my other sites the font does not show. Using firebug I determined that the font-face.css file was successfully being linked to and loaded. So why does the font not correctly load? Is there protection on the font files or something? I am using all fonts that I should be allowed to do this with, so I don't see why this is occurring. Maybe it is an apache issue, but I can download the font just fine when I link to it.
Oh, and just to clarify, I am not violating any copyrights by setting this up, all the fonts I am using are licensed to allow this sort of thing. I would however like to set up a way that only I can have access to this repository of fonts but that's another project.
This is because Firefox (from your mention of Firebug) thinks cross-domain, even subdomain, Web font embedding is a bad idea.
You can convince it to load fonts from your subdomain by adding this to the top-level .htaccess file of the subdomain where your fonts are being served (updated to adapt code from the same file in HTML5 Boilerplate):
<FilesMatch "\.(ttf|ttc|otf|eot|woff)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
In response to this:
I would however like to set up a way that only I can have access to this repository of fonts but that's another project.
The W3C spec for Access-Control-Allow-Origin doesn't say anything more than either a wildcard "*" or a specific domain. So far, I've found this SO answer which suggests validating the Origin header, but I think that's a Firefox-only header. I'm not sure about other browsers (they don't even need the .htaccess trick above for cross-domain Web fonts to work).
Another way to fix this in Firefox is to embed the font directly into the css file using base64 encoding. Especially nifty if you don't have access to some of the configuration mentioned above.
You can generate the necessary code on fontsquirrel.com: in the font-face Kit Generator choose expert mode, scroll down and select Base64 Encode under CSS Options - the downloaded Font-Kit will be ready to plug and play.
This also has the fringe benefit of reducing page load time because it requires one less http request.
If you do not want to allow resources from all domains but only from sub domain of your site, you should do it like:
# Allow font, js and css to be loaded from subdomain
SetEnvIf Origin "http(s)?://(.+\.)?(example\.com)$" ORIGIN_DOMAIN=$0
<IfModule mod_headers.c>
<FilesMatch "\.(eot|font.css|otf|ttc|ttf|woff|js|png|jpg|jpeg|gif)$">
Header set Access-Control-Allow-Origin %{ORIGIN_DOMAIN}e env=ORIGIN_DOMAIN
</FilesMatch>
</IfModule>
Source: http://www.webspeaks.in/2015/01/wordpress-allow-cross-domain-resources.html
Using http://www.fontsquirrel.com/fontface/generator in "expert" mode and choosing base64 as an option returned a stylesheet.css with the necessary base64 encoded data to use in our stylesheet. Seems to work in all browsers we've tested except IE8.
We run into this issue most when applying themes to 3rd party tools like salsa petition where we're forced to host the font.
Thanks for all the help everyone!
How can I add cache control code to .htaccess?
My site is slow and I found 35 static components without a far-future expiration date.
How can I add expiration data for that? I was informed that this could be done in the .htaccess file but I don't know how.
You can use something like this:
# Cache Files
<filesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=604800, public"
</filesMatch>
This caches any file ending with ico|pdf|flv|jpg..... for 604800 seconds, which is one week, you can change that number to cache for however long you feel you need.
I'm serving images two different ways:
Using a PHP script for profile pictures for example
By pointing to them directly, for icons and backgrounds for example
I'm in the process of handling their caching properly, and i'm totally new to this.
For the PHP script, i'm just adding a Last-Modified header to the response, and delivering a 304 status code if it's called again, if the file hasn't changed (using filemtime()).
For direct accesses, i'm using HTACCESS, but every rule i saw so far doesn't allow me to do the same as in my PHP script (checking if the file has changed, then serving a 304 or the file itself).
Here's the HTACCESS rule i'm planning to use:
Header unset Pragma
FileETag None
Header unset ETag
# cache images/pdf docs for 10 days
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
Header set Cache-Control "max-age=864000, public, must-revalidate"
Header unset Last-Modified
</FilesMatch>
From what i understand, the only way of updating a cached image is to rename it. Does someone know a way around it? By checking the image's last modification date for instance?
You could use mod_expires, if available:
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
ExpiresDefault "modification plus 10 days"
</FilesMatch>
What you are doing with PHP should do apache automatically for static files. It will set the Last-Modified header and respond with 304 if it will find if-Modified-since in the request. This is done automatically and has nothing to do with caching. It will not prevent repeated requests to your server, it will just save you bandwidth (and loading times for user) when the file is not modified by returning just 304 info instead of the whole file.
To prevent those repeated requests to your server, browser (and proxy servers) has to do some caching. You can control the caching either via HTTP headers or for HTML also via META tags. When you specify that the file is cacheable for 1 week, browser won't try to contact your server for 1 week (although most browsers are set to revalidate cache entries on first access after startup).
So you will either live with the possibility that some users will use old cached copy for some time (depends on the expiry header) or you must change your URL as Gerben suggested. Only then you can be 100% sure that everyone will get the new version (this is important for javascript as having some of the js files old and some new can make very strange errors). Nowadays almost every high performance website uses the file.ext?v=3 approach, so that they can set the expiry header to large values like 6 months.
As #Gumbo pointed out, "Apache should already do that for static files".
And that's true, Apache does that, so that kind of stuff works fine:
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
Header set Cache-Control "max-age=864000, public, must-revalidate"
</FilesMatch>
ps: Sorry #Gumbo, but i asked you to change your answer so that i can accept it, but you wouldnt do it and i had to close that question eventually, so.
I am plannig to set up something similar to the following:
https://wordpress.stackexchange.com/questions/6109/how-can-i-lock-down-an-old-wordpress-install-i-dont-intend-to-update
Basically the folders and files are generated like a cache for a php site.
What header info is sent for extensionless files? Is the header info stored in the text file like the modified date or something else?
I would like to stop using extensions for all site content.
For example:
/about - html page
/js - my sites javascript with appropriate header info
/logo - my sites logo
etc.
Are there any negatives or repercussions in setting extensionless files.
What about if I set up the caching system?
There are multiple options to set headers for static files, if they have no extension. For a whole directory it's easiest to use DefaulType in the .htaccess:
# js/ directory
DefaultType application/javascript
The sibling ForceType is sometimes also useful:
<Files about>
ForceType text/html
</Files>
But you can also set headers for individual files using e.g. a RewriteRule:
RewriteRule logo - [T=image/jpeg]
And another option is to use mod_meta. This allows to have each static file accompanied by a .meta file, which defines the sent MIME type.
Headers are being attached by the web server
Send a static file and you can see with Firebug or a similar tool what headers are being sent
To override a header that was attached by the server, you can use PHP's header function. Use the same header name as the one you want to override. For example, if you want to override\cancel the Content-Length header you would do header('Content-Length: ') (Although for this specific header it makes no sense to cancel it).
To attach headers to static files, you will need to do that (in Apache) in .htacces or the main configuration file of the Apache.
Use a Content Delivery Network (CDN)
Compress components with gzip
Configure entity tags (ETags)
Add Expires headers
If i don't have access to Apache configuration.
Use a Content Delivery Network (CDN)
This involves changing your hosting (for at least some files)
Compress components with gzip
Configure entity tags (ETags)
Add Expires headers
You can either:
Get access to your Apache configuration
Get someone who does have access to it to change it
I find "HOW TO SPEED UP YOUR SITE AND GET A YSLOW GRADE" is useful for me. Hope this help.
If you have grade A on every other YSlow rule then you're doing pretty well already and don't need to worry about those items. By the way, you can create custom rulesets in YSlow that are more tailored to your needs and server setup. So if you can't change any of these things, just remove them from the rules that YSlow uses.
Use a Content Delivery Network (CDN)
You can add your site domain as a CDN in YSlow. The idea of this one is to store static components on different domains to increase "parallelisation" (downloading more files at once). If you are using limited hosting then you could open a separate account and host some files there on a different domain.
Compress components with gzip
You can do this in PHP, using ob_start('ob_gzhandler'); at the very start of your scripts. This is a little more resource intensive so use Apache if possible.
Configure entity tags (ETags)
Remove this from the rule list, it's not necessary in 90% of cases. Yahoo only says to remove them because in the rare situation you have multiple servers in the back-end, the same file might have a different ETag if it comes from a different server. When each file comes from one server then ETags are a good thing and removing them is detrimental.
Add Expires headers
If you have no access to the server then you probably won't be able to change this. Ask your host about it. You may be able to override the server setting in your .htaccess file. You'd need the mod_expires Apache module. This page has some usage examples.
Paste this code bottom of .htaccess file
RewriteEngine On
# BEGIN Mod Header
ExpiresActive On
# Turn on Expires and set default expires to 10 years
# END Mod Header
# BEGIN Cache Control
Header set Expires "Thu, 15 Apr 2012 20:00:00 GMT"
Header unset ETag
FileETag None
#END Cache Control