Jump to content

Furls for JS and CSS that lead to maximum caching

KT Walrus

Recommended Posts

I think the current approach to having lots of individual JS and CSS files on a page with some loaded by the minify script isn't quite as efficient as it should be.

I suggest that you spend a little development time to implement a better solution.
I believe that one of the reasons that IPB3 feels slower than IPB2 for some is that the pages have lots of JS and CSS files that are loaded individually and some by using a query string (which some browser implement the standard of never caching files that use query strings - some browsers ignore the standard and cache anyway).

  1. Since browsers are required to never cache a file that uses a query string, make all JS and CSS files use FURLs (e.g., /javascript/ips.attach.js) as an option to loading the files through index.php.
  2. Don't combine any individual files into one URL. Load them in the script individually with maximum "forever" caching headers.
  3. Include a version number/last modified timestamp for a JS or CSS file in the FURL (e.g., ips.attach.v93802339.js). Don't change the underlying file name on disk. Since index.php (or another script that doesn't log in) is used to serve the files, the script will simply return the file with the version timestamp stripped out. The timestamps can be cached but recached on demand or whenever changed through the ACP.
  4. Keep a minified cache on disk of all files so the file is minified once (unless its timestamp changes and then the minified cache should be invalidated).

Since all JS and CSS would be served as FURLs with forever caching headers and the filenames are timestamped, this should result in most all browsers caching the files and only requesting a file to load only once. The key is the FURLs need to look static and not dynamic to the browser. By using the timestamps, the browser will download any changed files when the timestamp it sees in the FURL is changed, but otherwise will use the browser cache. Minifying isn't very important with this approach except for the first time the files are downloaded to the browser, but since you already use a dynamic script to minify some of the files (but not all), you may as well have this as an option when you minify. And, minifying provides a little obfuscation.

Link to comment
Share on other sites

Where was it determined that browsers should not cache requests with a query string? I've never heard that.

My understanding was that browsers are supposed to read the caching headers sent with a request, and honor those, regardless of the url. With url rewriting, why would a browser care if a request has a query string or not, knowing that the website owner could simply rewrite the request and serve the same content?

Using yslow and other tools, they indicate that the javascript and css files are caching just fine.

Link to comment
Share on other sites

[quote name='bfarber' date='21 September 2009 - 10:43 AM' timestamp='1253544199' post='1857843']
Where was it determined that browsers should not cache requests with a query string? I've never heard that.
Maybe this is old information. I got this idea by reading this article: http://carsonified.com/blog/features/webapps/serving-javascript-fast/

I just tried on the latest version of Safari in Snow Leopard and Safari seems to be caching URLs with query strings just fine (at least on this forum). So, maybe somewhere along the line, Safari decided not to take the speed penalty over a requirement that the other browsers ignore.

So, scratch that part of the suggestion. This just means that FURLs are not necessary.

But, I'd still like to have an option to timestamp the external file names and resolve these references to the corresponding actual file names (without the timestamp) on disk. This would require a rewrite rule (to strip the timestamp) or an index.php to serve up the correct file.

By changing the external file name when its modification time has changed, when the file does change at some time in the future, users will automatically get the new file without having to clear their browser caches. I know I have been confused at times.

I would think a lot of users are confused when they don't see a fix immediately after it is applied and have to be told to clear their caches.

Also, this same technique of timestamp'ing the external file name should apply to avatars and style_images. That is, serve up these infrequently changed but sometimes changed files using an index.php (or .htaccess rule) and having the markup always refer to the timestamp'ed file name.

I still think this is a good idea, even if the FURLs are not necessary to get the benefit of the caching.

At this point, you might ask why we don’t just add a query string to the end of the resource – /css/main.css?v=4. According the letter of the HTTP caching specification, user agents should never cache URLs with query strings. While Internet Explorer and Firefox ignore this, Opera and Safari don’t – to make sure all user agents can cache your resources, we need to keep query strings out of their URLs.

Link to comment
Share on other sites

[quote name='ssslippy' date='22 September 2009 - 03:52 PM' timestamp='1253631173' post='1860292']
BY default gzip does not gzip css and js. You must tell the server to.

but if your host has disabled mod_gzip, you're left with no option but to use php gzip handle and if you would, then why not have your board software do it for you :)

Link to comment
Share on other sites

That should do the job for now, reduced page output by about 150-200kb, you need Apache 2.x with mod_deflate enabled.

<ifmodule mod_deflate.c>

  AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript

Link to comment
Share on other sites


This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...