<?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; engineering</title>
	<atom:link href="http://www.artzstudio.com/tags/engineering/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>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>
		<item>
		<title>Optimizing Web Performance with AOL Pagetest</title>
		<link>http://www.artzstudio.com/2008/07/optimizing-web-performance-with-aol-pagetest/</link>
		<comments>http://www.artzstudio.com/2008/07/optimizing-web-performance-with-aol-pagetest/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 03:26:34 +0000</pubDate>
		<dc:creator>ArtzStudio</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[engineering]]></category>
		<category><![CDATA[operations]]></category>
		<category><![CDATA[pagetest]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.artzstudio.com/?p=6</guid>
		<description><![CDATA[In this screencast, I walk through how to analyze your site using the reports generated by AOL Pagetest, and explain why and how to go about addressing your pressing performance issues. Come for the tool demo, and stay to learn about the anatomy of an HTTP request, the importance of CDN&#8217;s and keep-alives, and a [...]]]></description>
			<content:encoded><![CDATA[<p>In this screencast, I walk through how to analyze your site using the reports generated by <a href="http://www.webpagetest.org">AOL Pagetest</a>, and explain why and how to go about addressing your pressing performance issues. Come for the tool demo, and stay to learn about the anatomy of an HTTP request, the importance of CDN&#8217;s and keep-alives, and a handy Apache module to concatenate CSS and JavaScript. Leave me feedback so I can improve it, and enjoy!</p>
<p><object width="640" height="480"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=1319060&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://www.vimeo.com/moogaloop.swf?clip_id=1319060&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="480"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.artzstudio.com/2008/07/optimizing-web-performance-with-aol-pagetest/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

