Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

Mitch Pronschinske is the Senior Content Curator (aka. "Lord of the Zones") at DZone. That means he writes and searches for the finest developer content in the land so that you don't have to. He often has hotdogs for lunch, likes to make his own ringtones, enjoys card and board games, and is married to an underwear model. Mitch is a DZone employee and has posted 1703 posts at DZone. You can read more from them at their website. View Full User Profile

RequireJS and Google Analytics' Innovative Async Script Loaders

03.18.2010
Email
Views: 4202
  • submit to reddit
As the code complexity of websites grow and assembly gets harder, these sites that more closely resemble web apps require more discrete JavaScript files and modules for development with optimized code in a small number of HTTP calls.  Node.js is a great JS framework for asynchronously running apps, but it starts with synchronous require() calls, which is a problem for require()-esque loader code.  Two projects that help out in these situations: RequireJS and an innovative asynchronous loader for Google Analytics.

RequireJS
RequireJS implements the CommonJS Transport/C proposal API.  This is a loader for plain JS files and more defined modules.  It works best in the browser, but it can also be used in other JavaScript environments like Rhino.  It allows easy debugging because it uses plain script tags for loading.  When the file defines a JS module via require.def(), RequireJS facilitates better CommonJS support and can load multiple versions of a module in a page.  RequireJS also supports module modifiers and has a plugin system for things like i18n string bundles and text file dependencies.

Require JS offers a solution for the require()-esque loader code with the ability to load nested dependencies, ease the use of front-end development with an optimization tool that helps deployment, and a form of #include/import/require.  Dojo, LABjs, and CommonJS script loading APIs don't solve all of the problems that RequireJS solves.  Here is the result of what RequireJS does:
// code that runs asynchronously when the library is loaded
require(["some/script.js"], function() {
//This function is called after some/script.js has loaded.
});

// defining the module and dependencies
require.def(
// The name of this module
"types/Manager",

// The array of dependencies
["types/Employee"],

// The function to execute when all dependencies have loaded. The arguments
// to this function are the array of dependencies mentioned above.
function (Employee) {
function Manager () {
this.reports = [];
}

// This will now work
Manager.prototype = new Employee();

// return the Manager constructor function so it can be used by other modules.
return Manager;
}
);

Google Analytics Asynchronous Tracking
Blocking was a longstanding problem for Google Analytics, but a new asynchronous loader is changing all that.  The Asynchronous API allows you to start pushing commands immediately because you can create an array that uses the push() method to put commands on a queue.  Once the Google Analytics code is done with its asynchronous loading, it takes over the array by wrapping the standard methods.  After that, the Asynchronous API can take the commands and send them back to Google Analytics and push() can perform more tasks.

This snipped is the minimum configuration needed to track a page asynchronously in Google Analytics:
<script type="text/javascript">

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
})();

</script>

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)