Most web-apps include a number of JavaScript and CSS files, that in most cases, need to be included/sourced on every page of the application. Doing so can bring up a few, while trivial, often annoying problems:
- Dependencies between scripts. For example, if you attempt to use a jQuery plugin before the base jQuery library has loaded into the browser you'll obviously see an error. Working out these dependencies before hand can save you a few headaches.
- Web-browsers and web-proxies cache your JavaScript and CSS files too often. I can't count the number of times on two hands when I made a small change to a JavaScript file, saved the change, refreshed my browser, and .... nothing. The web-browser didn't load the changed file; instead, it loaded the JavaScript from cache. Using a mechanism to always force the web-browser or web-proxy to reload your JavaScript and CSS can save you time.
Meet
Gagawa, an open source object-oriented HTML generation engine written in Java and PHP. You probably wouldn't build an entire site with Gagawa, but it's absolutely perfect for small HTML tasks, like solving this irritating dependency and caching problem.
Using Gagawa PHP, problem solved:
<?php
require_once("gagawa.php");
$js = array(
// The base jQuery library, needed by all other
// jQuery plugins and your jQuery code.
"/js/jquery-1.3.2.min.js",
// jQuery plugins; jQuery base needs to be loaded
// before you source these.
"/js/jquery.ui.min.js",
"/js/jquery.hotkeys.min.js",
// Some other, unrelated JavaScript library like
// underscore JS.
"/js/underscore.min.js",
// Your JavaScript, with dependencies on jQuery, the
// jQuery plugins and Underscore JS, should be loaded
// last.
"/js/yourjs.min.js"
);
$css = array(
"/css/othercss.min.css",
"/css/yourcss.css"
);
// Build <script ...></script> for each JavaScript
// we need, in order. Use time() to break browser
// caching.
foreach ($js as $url) {
$script = new Script("text/javascript");
echo $script->setSrc($url."?".time())->write();
}
// Build <link ...></link> for each CSS file we need,
// in order. Use time() to break browser caching.
foreach ($css as $url) {
$link = new Link();
$link->setHref($url."?".time())->setRel("stylesheet")->setType("text/css");
echo $link->write();
}
?>
This code snippet generates some solid output that fits nicely into the <head> of your HTML:
<script type="text/javascript" src="/js/jquery-1.3.2.min.js?1261531930"></script>
<script type="text/javascript" src="/js/jquery.ui.min.js?1261531930"></script>
<script type="text/javascript" src="/js/jquery.hotkeys.min.js?1261531930"></script>
<script type="text/javascript" src="/js/underscore.min.js?1261531930"></script>
<script type="text/javascript" src="/js/yourjs.js?1261531930"></script>
<link href="/css/yourcss.css?1261531930" rel="stylesheet" type="text/css"></link>
Note that each JavaScript and CSS file is loaded and added to your HTML, in order as desired, eliminating any stray dependency issues. Also, note that I'm appending "?" and the current
Epoch timestamp to the end of the JavaScript source URL, and CSS Href. PHP's
time() function works nicely here because I'll get a different timestamp on each page load. And as far as the browser (or a web-proxy) is concerned, "/js/yourjs.min.js?1261534594" is different than "/js/yourjs.min.js?1234567890" and will be treated as such. With this mechanism, every time you refresh the page, the browser will be forced to reload and reevaluate your scripts. Say goodbye to browsers caching and not recognizing your changes!
You can download the latest version of Gagawa at
http://code.google.com/p/gagawa/downloads/list. Also, if you're interested, other Gagawa examples can be found on the
Gagawa homepage.
If you're looking for a real, live, example of this technique in action
check out Onyx.
Merry Christmas.