Forcing (or highly encouraging) the browser to load webfonts directly from cache

2.5k views Asked by At

I'm trying to get my site to load a few webfonts, and I'd like to configure the reponse headers to tell browsers to cache the font, keep it there, and grab the file directly from the cache instead of sending a request to the server.

Google Webfonts does a great job at this; even when I hard reload in Chrome or Firefox, the font loads directly from cache without even checking if there's a newer version available (it returns a 200 status, with (from cache) displayed in Chrome.

However, when I send my response (I'm using nginx as a web server) with all of the usual cache headers, it fails to do this. It'll be great even getting to the point where the browser won't send a request (and the server sending a 304) on a regular page reload.

Here are Google's headers (from one of their WOFF files) served from cache:

HTTP/1.1 200 OK
status: 200 OK
version: HTTP/1.1
access-control-allow-origin: *
age: 13190
alternate-protocol: 80:quic
cache-control: public, max-age=31536000
content-length: 28588
content-type: font/woff
date: Fri, 13 Dec 2013 23:51:45 GMT
expires: Sat, 13 Dec 2014 23:51:45 GMT
last-modified: Thu, 13 Sep 2012 17:47:52 GMT
server: sffe
timing-allow-origin: *
x-content-type-options: nosniff
x-xss-protection: 1; mode=block

Here's one of the responses my server is sending (served 'live'):

HTTP/1.1 200 OK
Server: nginx
Date: Sat, 14 Dec 2013 03:40:37 GMT
Content-Type: font/opentype
Content-Length: 244744
Last-Modified: Mon, 09 Dec 2013 22:35:59 GMT
Connection: keep-alive
Expires: Sun, 14 Dec 2014 03:40:37 GMT
Cache-Control: max-age=31536000
Access-Control-Allow-Origin: *
Cache-Control: public, max-age=315360000
Accept-Ranges: bytes

(I realize that there are 2 Cache-Control headers, but according to spec, that should be fine? The first one is nginx's, the second one I added manually to add 'public').

What is causing the big difference in behaviour between the two responses?

1

There are 1 answers

2
drankin2112 On

I am not overly hip on this stuff, but do have a little experience in configuring web servers. I decided to take a quick look at your issue and I found information on the nginx website that might be useful.

http://nginx.org/ru/docs/http/ngx_http_headers_module.html

But, the main thing I saw was that the nginx responce isn't sending the "Age" header.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Here is the main exerpt from w3c:

14.6 Age

  The Age response-header field conveys the sender's estimate of the
  amount of time since the response (or its revalidation) was
  generated at the origin server. A cached response is "fresh" if
  its age does not exceed its freshness lifetime. Age values are
  calculated as specified in section 13.2.3.

       Age = "Age" ":" age-value
       age-value = delta-seconds

  Age values are non-negative decimal integers, representing time in
  seconds.

  If a cache receives a value larger than the largest positive
  integer it can represent, or if any of its age calculations
  overflows, it MUST transmit an Age header with a value of
  2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST
  include an Age header field in every response generated from its
  own cache. Caches SHOULD use an arithmetic type of at least 31
  bits of range.

Sending the "Age" header will probable solve your problem. Good luck!