<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ArtzStudio &#187; javascript</title>
	<atom:link href="http://www.artzstudio.com/tags/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.artzstudio.com</link>
	<description>Dave Artz and his discoveries in web design and development.</description>
	<lastBuildDate>Fri, 03 Jun 2011 04:57:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Using mod_concat to Speed Up Start Render Times</title>
		<link>http://www.artzstudio.com/2008/08/using-modconcat-to-speed-up-render-start/</link>
		<comments>http://www.artzstudio.com/2008/08/using-modconcat-to-speed-up-render-start/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 14:43:57 +0000</pubDate>
		<dc:creator>ArtzStudio</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[operations]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://www.artzstudio.com/?p=45</guid>
		<description><![CDATA[The most critical part of a page&#8217;s load time is the time before rendering starts. During this time, users may be tempted to bail, or try a different search result. For this reason, it is critical to optimize the &#60;head&#62; of your HTML to maximum performance, as nothing will be visible until it finishes loading [...]]]></description>
			<content:encoded><![CDATA[<p><img class="doodle" src="http://www.artzstudio.com/files/mod_concat/concat-js.png" alt="" /></p>
<p>The most critical part of a page&#8217;s load time is the time before rendering starts. During this time, users may be tempted to bail, or try a different search result. For this reason, it is critical to optimize the <code>&lt;head&gt;</code> of your HTML to maximum performance, as nothing will be visible until it finishes loading the objects inside.</p>
<p>One easy way to speed up rendering during this crucial time is to <a href="http://www.websiteoptimization.com/speed/tweak/http/">combine your CSS and JavaScript</a>, saving the performance tax associated with every outbound request. While easy in theory,  in practice this can be difficult, especially for large organizations.</p>
<p>For example, say your ad provider wants you to include their script in a separate file so they can make updates whenever they choose. So much for combining it into your site&#8217;s global JS to reduce the request, eh?</p>
<p><a href="http://code.google.com/p/modconcat/">mod_concat</a> makes combining shared libraries easy by providing a way to dynamically concatenate many files into one.</p>
<h2>See mod_concat in Action</h2>
<p>We created a couple test pages to show the benefits here. In our <a href="http://lime.holsman.net:8001/concat/without.html">first example without mod_concat</a>, we see a typical large scale website with many shared CSS and JavaScript files loaded in the <code>&lt;head&gt;</code> of the HTML. There are scripts for shared  widgets (two of them video players), ad code, and more that typically plague many major web sites.</p>
<p>You can check out the <a href="http://pagetest.patrickmeenan.com:8080/results/62Q/">Pagetest results</a> here, and check out the time to start render (green bar):</p>
<p><img src="http://www.artzstudio.com/files/mod_concat/without-concat.png" alt="pagetest waterfall with mod concat disabled" width="631" height="290" /></p>
<p>In the test page, we have 12 JavaScript files and 2 CSS files, a total of 14 HTTP requests in the <code>&lt;head&gt;</code>. I have seen worse. The green vertical bar is our Start Render time, or the time it took for the user to see something, at <strong>4 seconds!</strong></p>
<p>We can see that the time spent downloading is typically the green time, or the time to first byte. This happens on every object, simply for existing! A way to make this not happen, is to combine those files into one, larger file. Page weight (bytes) stay the same, but Requests are reduced significantly.</p>
<p>Let&#8217;s take a look at our <a href="http://pagetest.patrickmeenan.com:8080/results/62P/">Pagetest results</a> of a <a href="http://lime.holsman.net:8001/concat/with.html">second example with mod_concat enabled</a>.</p>
<p><img src="http://www.artzstudio.com/files/mod_concat/with-concat.png" alt="pagetest waterfall of music page with modconcat enables" width="614" height="130" /></p>
<p>Notice our the number of Requests went from 14 to 5, and we saved <strong>1.5 seconds</strong>! We probably could have made an even faster example by moving to just 2 requests (one for CSS and one for JS), but the speed win here is clear.</p>
<h2>How mod_concat Works</h2>
<p><a href="http://code.google.com/p/modconcat/">mod_concat</a> is a module for Apache built by <a href="http://feh.holsman.net/">Ian Holsman</a>, my manager at AOL and a <a href="http://people.apache.org/~ianh/">contributor to Apache</a>. Ian gives credit in the <a href="http://modconcat.googlecode.com/files/mod_concat.pdf">mod_concat documentation</a> to David Davis, who did it while working at Vox, and perlbal.</p>
<p>The idea is straightforward, and you can pretty much figure out how it works by viewing the <a href="http://lime.holsman.net:8001/concat/with.html">source code of our second example</a>:</p>
<p><!-- .example b {background-color:#ffc;font-weight:normal} --></p>
<pre class="example">&lt;link rel="stylesheet" type="text/css" media="screen" ←
	href="<strong>http://lemon.holsman.net:8001/cdn/??music2.css,common.css</strong>" /&gt;
&lt;script type="text/javascript"  ←
	src="<strong>http://lemon.holsman.net:8001/cdn/??music2.js,mp.js,dalai_llama.js,ratings_widget.js,widget_config.js,common.js</strong>"&gt;&lt;/script&gt;
&lt;script language="javascript" type="text/javascript" ←
	src="<strong>http://tangerine.holsman.net:8001/o/??journals_blog_this.js,adsWrapper.js,flashtag.js,feeds_subscribe.js</strong>"&gt;&lt;/script&gt;
&lt;script type="text/javascript"  ←
	src="<strong>http://orange.holsman.net:8001/digital/??dm_client_aol.js,cannae.js</strong>"&gt;&lt;/script&gt;</pre>
<p>You can see in the highlighted code above that a single request is referencing multiple files, and the server is returning the concatenated version. The URL takes the following format:</p>
<p><!-- .example b {font-weight:normal}  --></p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF">optional/path/</strong><strong style="background-color:#FFFF99">??</strong><strong style="background-color:#99FF99">filename1.js,</strong><strong style="background-color:#FFCC99">directory/filename2.js,</strong><strong style="background-color:#CCFF66">filename3.js</strong></pre>
<p>Let&#8217;s break it down.</p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF"></strong></pre>
<p>The first bit should be straight forward, it&#8217;s the host name.</p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF">optional/path/</strong><strong style="background-color:#FFFF99"></strong></pre>
<p>Next comes the optional path to the files. This is important, because you can&#8217;t concatenate files <strong> above this directory</strong> if you include it. However, it allows you to optimize a bit so you don&#8217;t need to keep referencing the same path for files below this directory.</p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF">optional/path/</strong><strong style="background-color:#FFFF99">??</strong><strong style="background-color:#99FF99"></strong></pre>
<p>The ?? then triggers the magic for the files that come next. It&#8217;s a special signal to Apache that it&#8217;s time to combine files!</p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF">optional/path/</strong><strong style="background-color:#FFFF99">??</strong><strong style="background-color:#99FF99">filename1.js,</strong><strong style="background-color:#FFCC99"></strong></pre>
<p>If the file is in the current directory, you can simply include it  next, followed by a comma &#8220;,&#8221;.</p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF">optional/path/</strong><strong style="background-color:#FFFF99">??</strong><strong style="background-color:#99FF99">filename1.js,</strong><strong style="background-color:#FFCC99">directory/filename2.js,</strong><strong style="background-color:#CCFF66"></strong></pre>
<p>If you need to go a bit further in the directory hierarchy, you can do that too.</p>
<pre class="example"><strong style="background-color:#FFCCFF">http://www.yourdomain.com/</strong><strong style="background-color:#CCCCFF">optional/path/</strong><strong style="background-color:#FFFF99">??</strong><strong style="background-color:#99FF99">filename1.js,</strong><strong style="background-color:#FFCC99">directory/filename2.js,</strong><strong style="background-color:#CCFF66">filename3.js</strong></pre>
<p>You can include as many files as you wish as long as they fall within the same server directory path defined early on in your <code style="background-color:#CCCCFF">optional/path/</code>.</p>
<h2>Performance and Caching Considerations</h2>
<p>mod_concat uses the Last-Modified date of the most recently modified file when it generates the concatenated version. It should honor any max-age or expires Cache Control headers you set for the path in your server or htaccess configuration.</p>
<p>If you have a far future expires or max-age header, to bust the cache  you will need to rename one of the files or directory names in the string, and then the user will download the entire concatenated version again.</p>
<p>Because mod_concat is an Apache module, performance is near instantaneous. Performance is improved further still if the server happens to be an origin point for a CDN, as it gets cached on the edge like an ordinary text file for as long as you tell it to, rarely hitting your servers.</p>
<h2>Same Idea, Different Platforms</h2>
<p>For regular folks like myself who don&#8217;t have the ability to install Apache modules with their hosting provider (cough, Lunarpages, cough), mod_concat is not the best option. The idea of concatenating JavaScript and CSS has been implemented on other platforms, and I will briefly call out those I found in my brief Googling &#8211; feel free to list more that you know of.</p>
<h3>Rakaz&#8217;s PHP Combine Solution</h3>
<p>Niels Leenheer of rakaz.nl has a nice solution for PHP. Niels writes:</p>
<blockquote><p>Take for example the following URLs:</p>
<ul>
<li>http://www.creatype.nl/javascript/prototype.js</li>
<li>http://www.creatype.nl/javascript/builder.js</li>
<li>http://www.creatype.nl/javascript/effects.js</li>
<li>http://www.creatype.nl/javascript/dragdrop.js</li>
<li>http://www.creatype.nl/javascript/slider.js</li>
</ul>
<p>You can combine all these files to a single file by simply changing the URL to:</p>
<ul>
<li>http://www.creatype.nl/javascript/prototype.js,builder.js,effects.js,dragdrop.js,slider.js</li>
</ul>
</blockquote>
<p>Niels takes advantage of Apache&#8217;s Rewrite rules as such to make the <a href="http://rakaz.nl/projects/combine/combine.phps">combine PHP script</a> transparent to the template designer:</p>
<pre>RewriteEngine On
RewriteBase /
RewriteRule ^css/(.*\.css) /combine.php?type=css&amp;files=$1
RewriteRule ^javascript/(.*\.js) /combine.php?type=javascript&amp;files=$1</pre>
<p>This is nice because it keeps the PHP script and HTML template separate from each other, just like mod_concat.</p>
<h3>Ed Elliot&#8217;s PHP Combine Solution</h3>
<p><a href="http://www.ejeliot.com/blog/72">Ed&#8217;s solution for combining CSS and JavaScript</a> is less flexible from a front-end template designer&#8217;s perspective, as you&#8217;ll need to touch PHP code to update the files being merged together. However, the advantages I see to his take on the problem are:</p>
<ul>
<li>He masks the actual file names being combined, and</li>
<li>A new version number is automatically generated to <strong>automatically bust the cache</strong></li>
</ul>
<p>For folks who don&#8217;t mind digging into PHP, the above benefits may be worth the effort. I especially like the cache-busting, as it allows me to put a far future expires header without worrying if my users will get the update or not.</p>
<h3>PHPSpeedy</h3>
<p>Finally among the PHP scripts I found is <a href="http://aciddrop.com/php-speedy/">PHPSpeedy</a>. Also available as a <a href="http://aciddrop.com/2008/03/07/php-speedy-wordpress-plugin-preview-release/">plug-in for WordPress</a>, PHPSpeedy appears to get the job done like the others, with the added benefit of <strong>automatic minification</strong>.</p>
<p>This might be useful for folks, but I&#8217;m the obfuscator type and promote that for production build processes. I&#8217;d love to see a safe obfuscator like <a href="http://developer.yahoo.com/yui/compressor/">YUICompressor</a> written in C so we could turn it into a module for Apache.</p>
<h3>Lighthttpd and mod_magnet</h3>
<p>For users of Lighthttpd, <a href="http://trac.lighttpd.net/trac/wiki/Docs:ModMagnet">mod_magnet</a> can be used to do the concatenation. It appears similar in nature to Rakaz&#8217;s solution, though I will leave it to you to dig in further as it seems to be fairly involved. This <a href="http://www.cakephp.nu/faster-page-loads-bundle-your-css-and-javascript-lighttpd-mod_magnet-lua">blog post by Christian Winther</a> should help get you started.</p>
<h3>ASP.Net Combiner Control</h3>
<p>Cozi has <a href="http://blogs.cozi.com/tech/2008/04/combining-js-an.html">developed an ASP.net control to combine multiple JS and CSS</a> into a single file, and includes a cool versioning feature much like Ed Elliot&#8217;s script. It&#8217;s very easy to use; you simply wrap the script with the control tag in the template:</p>
<pre>&lt;WebClientCode:CombinerControl ID="CombineScript" runat="server"&gt;&lt;script src=" ←
	script/third-party/jquery.js" type="text/javascript"&gt;&lt;/script&gt;&lt;script src=" ←
	script/third-party/sifr.js" type="text/javascript"&gt;&lt;/script&gt;&lt;script src=" ←
	script/third-party/soundmanager.js" type="text/javascript"&gt;&lt;/script&gt;&lt;script src=" ←
	script/cozi_date.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/WebClientCode:CombinerControl&gt;</pre>
<p>It then outputs the following code at runtime:</p>
<pre>&lt;script src="../Combiner/Combiner.ashx?ext=js ←
	&amp;ver=59169b00 ←
	&amp;type=text%2fjavascript ←
	&amp;files=!script'third-party*jquery*sifr*soundmanager*!script*cozi_date*" ←
	type="text/javascript"&gt;&lt;/script&gt;</pre>
<p>The only problem I see with their approach is that since the output file has query parameters, Safari and Opera <strong>won&#8217;t honor cache control headers </strong>as it assumes it is a dynamic file. This is why simply adding ?ver=123 to bust the cache is not a good idea for those browsers.</p>
<h3>Java JSP Taglib &#8211; pack:tag</h3>
<p>Daniel Galán y Martins developed a <a href="http://www.galan.de/projects/packtag">combine solution for Java called packtag</a>. It follows in the spirit of PHPSpeedy and provides additional optimizations such as minification, GZIP, and caching.</p>
<p>It&#8217;s not obvious from the documentation what the output of the combined script looks like, but in a <a href="http://www.galan.de/files/overview640.png">flow graphic</a> it seems to include a version number, which would be cool.</p>
<p>The code  to do the combination goes right in the JSP template, and looks like this:</p>
<pre>&lt;pack:script&gt;
&lt;src&gt;/js/validation.js&lt;/src&gt;
&lt;src&gt;/js/tracking.js&lt;/src&gt;
&lt;src&gt;/js/edges.js&lt;/src&gt;
&lt;/pack:script&gt;</pre>
<p>CSS can be combined too. The syntax appears to be quite flexible:</p>
<pre>&lt;pack:style&gt;
&lt;src&gt;/main.css&lt;/src&gt;
&lt;src&gt;../logout/logout.css&lt;/src&gt;
&lt;src&gt;/css/**&lt;/src&gt;
&lt;src&gt;http://www.example.com/css/browserfixes.css&lt;/src&gt;
&lt;src&gt;/WEB-INF/css/hidden.css&lt;/src&gt;
&lt;/pack:style&gt;</pre>
<p>As you can see this idea has been implemented in many languages, some with additional innovations worth considering, so if you can&#8217;t leverage mod_concat, at least use something similar as the benefits are well worth it.</p>
<h2>Final Thoughts</h2>
<p>mod_concat is a performant, cross-language, high-scale way to build concatenation into your build process while maintaining files separately. While it lacks automatic versioning (<em>Ian, can we do this?</em>), it provides a clean way to dynamically merge JS and CSS together without touching a bit of server-side code, and it works across server-side languages.</p>
<p>One feature I&#8217;d like to see added is a  debug mode. For example, if the code throws an error it may not be apparent based on line number what file is having issues. Perhaps the filename could be included in comments at the start.</p>
<p>Remember, improving the time to start rendering the page is critical and you should focus on this first. With tools like mod_concat and the others mentioned here, there should be little excuse to implement this into your routine. Little pain, a lot to gain.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artzstudio.com/2008/08/using-modconcat-to-speed-up-render-start/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Beating Blocking JavaScript: Asynchronous JS</title>
		<link>http://www.artzstudio.com/2008/07/beating-blocking-javascript-asynchronous-js/</link>
		<comments>http://www.artzstudio.com/2008/07/beating-blocking-javascript-asynchronous-js/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 19:03:51 +0000</pubDate>
		<dc:creator>ArtzStudio</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[engineering]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false">http://www.artzstudio.com/?p=10</guid>
		<description><![CDATA[MSN is now implementing a technique for loading JavaScript in a way that doesn&#8217;t stall the rendering of the document. They use Dynodes, a technique I also recommend for loading functionality on demand so it only consumes bandwidth when it is needed. JavaScript Blocks Everything To see the problem, view a Pagetest waterfall report of [...]]]></description>
			<content:encoded><![CDATA[<p><img class="doodle" src="http://www.artzstudio.com/files/asynchronous-js/blocking-js.png" alt="" width="193" height="118" />
<p>MSN is now implementing a technique for loading JavaScript in a way that doesn&#8217;t stall the rendering of the document. They use <a href="http://www.mindsack.com/uxe/dynodes/"><i>Dynodes</i></a>, a technique I also recommend for loading functionality on demand so it only consumes bandwidth when it is needed.</p>
<h2>JavaScript Blocks Everything</h2>
<p>To see the problem, view a <a href="http://www.webpagetest.org">Pagetest waterfall report</a> of pretty much any website today, or see this <a href="http://pagetest.patrickmeenan.com:8080/results/ZB/">recent run of AOL.com</a>. Notice that <b>1 second </b>is spent downloading and executing JavaScript, <b>one at a time</b>.</p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/aol-blocking.png" alt="waterfall graphic of aol javascript blocking rendering" width="519" height="227" /></p>
<p> One by one, folks! This is how all browsers load JavaScript (unless the <code>defer</code> attribute is used in IE) when called from your standard <a href="http://www.w3schools.com/TAGS/tag_script.asp">HTML <code>&lt;script&gt;</code> element</a>.</p>
<p>However, viewing a <a href="http://pagetest.patrickmeenan.com:8080/results/1WD/waterfall.html?run=1">waterfall report of MSN</a>, we can see that they call 3 JavaScript files (dap.js, hptr.js, and hp.js) asynchronously, and  allow the subsequent CSS files to load right away. </p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/msn-no-blocking.png" alt="waterfall graphic of msn javascript not blocking" width="508" height="205" /></p>
<p>Had their scripts loaded in the standard way, dap.js, hptr.js, and hp.js would delay the page for <b>1.4 seconds!</b></p>
<h2>Loading JavaScript Asynchronously</h2>
<p>MSN is using standard DOM functions to create and append a script element to the HTML document&#8217;s <code>&lt;head&gt;</code> element. This technique, originally coined as <a href="http://www.mindsack.com/uxe/dynodes/"><i>Dynodes</i></a>, is encapsulated in a JavaScript loader, much like the one used by JS frameworks such as Dojo. </p>
<p>We downloaded and formatted the <a href="http://www.artzstudio.com/files/asynchronous-js/msn-source-code-formatted.html">MSN.com HTML source code</a> so you can have a closer look at it. Start on line 297 which kicks off a process to a function aptly named <code>JS</code>:</p>
<pre>(function(){}).JS(Msn.Page.Track).JS(Msn.Page.Js)</pre>
<p>Note that it is passed in two URLs defined back on Lines 13-19:</p>
<pre>
Msn={
	Page:{
		SignedIn:'False',
		Js:'<b>http://stj.msn.com/br/hp/en-us/js/46/hp.js</b>',
		Track:'<b>http://stj.msn.com/br/hp/en-us/js/46/hptr.js</b>',
</pre>
<p>The <code>JS</code> function kicks off a  method that  pulls down these two scripts. Take a look at line 130 to get to the heart of this technique:</p>
<pre>var c=g.createElement("script");
c.type="text/javascript";
c.onreadystatechange=n;
c.onerror=c.onload=k;
c.src=e;
p.appendChild(c)</pre>
<p>The <code>&lt;script&gt;</code> element (<code>c</code>) is appended to the <code>&lt;head&gt;</code> element (<code>p</code>), as defined back on line 113.</p>
<p>MSN also appears to be closely monitoring the load of all the scripts called by <code>JS</code>, in case something happens during the process. Event handlers are set on <code>readystatechange</code>, <code>error</code>, and <code>load</code> to stop the polling process (fired every 100ms) once the script is finished.</p>
<p>Their code is quite obfuscated and difficult to follow, but you can look for the timeout function on line 125. There also appears to be an optional parameter to kill the process after a specified period of time.</p>
<h2>JS Loader Prototype</h2>
<p>We designed a <a href="http://www.artzstudio.com/files/asynchronous-js/js-loader.html">JS Loader Prototype</a> (not nearly as fancy as MSN&#8217;s) that illustrates the benefits of this technique, and tested behaviors in IE and Firefox.</p>
<p>In our prototype (we strongly suggest you view the source now), the code is organized into 4 sections:</p>
<ul>
<li>JavaScript #1 and #2 are called from  a <code>&lt;script&gt;</code> block in the  <code>&lt;head&gt;</code> using our JS Loader function.</li>
<li>JavaScript #3 and #4 follow next, called by the JS Loader in a <code>&lt;script&gt;</code> block in the <code>&lt;body&gt;</code>.</li>
<li>JavaScript #5 and #6 are called after some text again by the JS Loader,  from a second <code>&lt;script&gt;</code> block in the <code>&lt;body&gt;</code>.</li>
<li>Finally, #7 and #8 are loaded in the traditional, HTML <code>&lt;script&gt;</code> element fashion.</li>
</ul>
<p>In Internet Explorer, the script files queued up normally and the screen was not blocked for any period of time (until #7 and #8). Notice a <b>very short Start Render time</b> in our <a href="http://pagetest.patrickmeenan.com:8080/results/1WT/waterfall.html?run=1">test run at Pagetest</a>, and JS loading <b>as fast as HTTP1.1&#8242;s 2 connection per domain limit will allow it</b>:</p>
<p><a href="http://pagetest.patrickmeenan.com:8080/results/1WT/waterfall.html?run=1"><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-ie.png" alt="waterfall chart of js loader prototype in ie showing full asynchronous load" width="731" height="160" /></a></p>
<p>In Firefox, however, any content below the <b>next</b> inline HTML <code>&lt;script&gt;</code> section is blocked until the scripts from the <b>previous</b> inline HTML <code>&lt;script&gt;</code> section called by the loader are complete. <a href="http://www.artzstudio.com/files/asynchronous-js/js-loader.html">You have to see it to believe it!</a></p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-ff.png" alt="waterfall chart of firefox blocking until all js has download in each script block" width="547" height="172" /></p>
<p>Notice in the above chart, within each script block both JavaScript must fully load before the next script block is allowed to start processing. The takeaway here is to include as many JS Loader calls as possible in one script block.</p>
<p>We developed a workaround for this issue by including a <b>timeout delay</b> before calling the script. This allows Firefox to continue rendering like IE and Safari, and affords the fastest possible download. <a href="http://www.artzstudio.com/files/asynchronous-js/js-loader-ff.html">See the updated JS Loader Prototype for Firefox here.</a></p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-ff-delay.png" alt="waterfall of updated prototype showing that firefox no longer blocks other scripts" width="553" height="168" /></p>
<p>We put a longer delay on the first script (10 seconds) so you can see that Firefox no longer waits until the script block has completed before loading others. The important bit of code looks like this:</p>
<pre>
js:function(url)
{
	// If you want to call IE and Safari straight up without the delay, uncomment this.
	// (navigator.userAgent.search('Firefox')) ? js = setTimeout("artz.create('"+url+"')", 0) : artz.create(url);
	js = setTimeout("artz.create('"+url+"')", 0);
},
create:function(url)
{
	s = artz.ce('script');
	s.type = 'text/javascript';
	s.src = url;
	artz.tag('head')[0].appendChild(s);
},
</pre>
<p>You will be pleased to know that Safari renders much like IE, with the added benefits of <b>4 open socket connections!</b></p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-safari.png" alt="waterfall shot of safari with 4 open socket connections" width="508" height="270" /></p>
<p>Hopefully the benefits to this approach are clear. With a large site like MSN faithfully using Dynodes for their scripts, it might just be the time to <b>standardize on this approach</b>.</p>
<h2>Race Condition Challenges</h2>
<p>Not so fast! (pardon the pun) There are some additional considerations we will need to think through when moving in this direction.</p>
<ul>
<li>JavaScript <b>functions</b> in the external scripts <b>may not be available </b>when inline HTML JavaScript functions call for them.</li>
<li>Along the same lines, even if Script A is called before Script B, Script B may finish and execute before Script A. </li>
<li>DOM <b>elements may not yet be available</b> in the HTML should an external script need them to hook events, access data from, etc.</li>
</ul>
<p>In tackling the above, we would first recommend following the <a href="http://en.wikipedia.org/wiki/Progressive_enhancement">Progressive Enhancement</a> approach, and work to completely eliminate inline HTML JavaScript function calls. The external scripts can latch any events needed on to links, buttons, etc., once they are ready.</p>
<p>While race conditions may still exist, a way to solve this is using the <code>setInterval</code> function to initialize your functions where you know a race condition may exist.</p>
<pre>function id(id){return document.getElementById(id)}

var oranges =
{
	init: function()
	{
		if(id('oranges'))
		{
			clearInterval(oranges_init);
			alert('We have oranges!');
			// We may proceed with orange code!
		}
	}
}

oranges_init = setInterval("oranges.init()", 100);</pre>
<p>We recommend using a period of 100ms to go easy on the CPU, and <a href="http://www.useit.com/papers/responsetime.html">still feel instantaneous to users</a>. To see this code in action, have a look at our <a href="http://www.artzstudio.com/files/asynchronous-js/id-polling.html">ID Polling Prototype</a>.</p>
<h2>Document.Wrong</h2>
<p>External scripts loaded that include the infamous<code> document.write</code> method executed by the script  will cause problems with this technique. Be sure to wrap it in a function and call it  from the HTML if you decide to head down this path. We hope that by now, you have thrown this ancient tool away.</p>
<p>Advertising vendors&#8230;this means <b>you</b>!</p>
<h2>Final Thoughts</h2>
<p>This technique has been on the back shelf for some time due to the tricky Firefox and race condition issues. </p>
<p>That said, if we are careful, and with MSN proving its value, now just may be the time to <b>adopt Dynodes as a standard JavaScript loading practice</b>.</p>
<p>Leave us a comment with your thoughts, questions, and <b>concerns</b>, and post links to implementations that leverage this!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artzstudio.com/2008/07/beating-blocking-javascript-asynchronous-js/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

