Expires and CDNS - YSlow Problems

davewoodhall picture davewoodhall · Feb 26, 2014 · Viewed 35.4k times · Source

Let me first mention that I have done some digging but can't seem to find a proper answer to what I'll looking for.

I'm working on a site where I am using a few external resources:

Use a Content Delivery Network (CDN)

I'm getting an "F" grade on "Use a Content Delivery Network (CDN)". A different SO Post links to the YSlow FAQ (direct link) but this seems to indicate that I need to define my CDN's on my browser, which seems to be a quick fix for me, but this does not solve the problem on other browsers and/or devices.

Add Expires headers

As for the "Add Expires headers" grade,I get an E. Problem is, this is what I'm getting:

There are 3 static components without a far-future expiration date.

(2014/2/26) http://fonts.googleapis.com/css?...
(2014/2/26) http://www.google-analytics.com/analytics.js
(2014/2/26) http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js

How would I go in order to correct this? My local files are all taken care of by my .htaccess as shown, here:

AddType image/x-icon .ico

ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType image/ico "access plus 1 year"
ExpiresDefault "access plus 7 days"

<FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$">
    # access plus 1 year
    Header set Cache-Control "max-age=31536000"
</FilesMatch>

This SO post seems to suggest it is either impossible, or I call upon a local script where I use my bandwidth to load (and cache) the required external files.

So, with these things in mind, here is what I'm looking at:

  1. External ressources should be CDN's, but YSlow reads my local preferences which will vary from user to user, so I need an alternative to the about:config solution proposed by the YSlow official site.
  2. Expires are set by the server where the file is, so I don't seem to have access to defining it's expiration values. So, from what I gather, I could carry these files onto my server or use a local PHP file and cache it from said PHP file located my server, but this doesn't seem optimal. Is there a way to go around this?

Answer

BrianC picture BrianC · Feb 27, 2014

Short answer:

You can't control much when you're loading resources from external servers like that, but it may still be okay for your site. When using a tool like YSlow it's important to not get caught up into an "A" grade for everything. It's best to understand the hints the tool is giving you, and make decisions accordingly.

Longer answers:

Content Delivery Network

YSlow will report lower grades for any domains it doesn't recognize as a CDN. You can add CDN hostnames, then it will reflect a better grade. I would add fonts.googleapis.com and ajax.googleapis.com because both behave like CDNs. Think of it as saving a preference in your copy of YSlow. Adding the domains here doesn't actually change your performance, it just improves your score.

Expires Headers

You can't control expires headers for content you're loading from a different site. Options you could consider:

  1. Continue using external sites; in this case these are pretty well behaved and your performance will probably be pretty good. Just ignore the low grade that YSlow is giving you.
  2. Host your fonts and jQuery files locally, then set far-futures expires headers as you've shown in your .htaccess. This would give you a better YSlow grade, but actual performance may be worse if your server is slower than the CDNs. (see this SO question)
  3. Use external sites but adjust your URL; in the case of jQuery, if you specify on more version level (1.8.0 instead of 1.8) you will get a far future expires header (see this SO question)