<?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>Cloud Four &#187; Performance</title>
	<atom:link href="http://www.cloudfour.com/category/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cloudfour.com</link>
	<description>Expert Web and Mobile Design, Development and Strategy</description>
	<lastBuildDate>Tue, 31 Jan 2012 17:22:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Preferred solutions for responsive images</title>
		<link>http://www.cloudfour.com/preferred-solutions-for-responsive-images/</link>
		<comments>http://www.cloudfour.com/preferred-solutions-for-responsive-images/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 21:53:34 +0000</pubDate>
		<dc:creator>Jason Grigsby</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=2159</guid>
		<description><![CDATA[Scott Jehl recently tweeted: I concur. A couple of months ago, I asked what you preferred as a solution for responsive images. At the time, I didn’t have a strong opinion. But over the last couple of weeks, I’ve become increasingly comfortable with a direction that Scott Jehl, Ethan Marcotte and I discussed on twitter [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/scottjehl">Scott Jehl</a> recently tweeted:</p>
<p style="text-align:center;"><a href="http://twitter.com/#!/scottjehl/status/134437217262247936"><img src="http://www.cloudfour.com/wp-content/uploads/2011/11/scott-time-to-shift-conv2.png" alt="Time to shift the responsive imgs discussion to how we'd actually prefer to do things, and then make it happen. Attrs? CSS? JS? New headers?"  /></a></p>
<p>I concur. A couple of months ago, I asked <a href="http://www.cloudfour.com/responsive-imgs-part-3-future-of-the-img-tag/">what you preferred as a solution for responsive images</a>. At the time, I didn’t have a strong opinion. But over the last couple of weeks, I’ve become increasingly comfortable with a direction that Scott Jehl, Ethan Marcotte and I <a href="http://storify.com/grigs/future-responsive-images">discussed</a> on twitter recently.</p>
<h3>Short run solution: preparse attribute</h3>
<p>In September, Scott Jehl proposed a solution that might be fairly easy for browser makers to implement in the short run: adding a preparse attribute to the script tag.</p>
<p style="text-align:center;"><a href="https://twitter.com/#!/scottjehl/status/119836986101075968"><img src="http://www.cloudfour.com/wp-content/uploads/2011/11/scott-preparse.png" alt="@grigs silly: &lt;script preparse&gt; //document.src references raw HTML src document.src = document.src.replace( pattern, replacement ) &lt;/script&gt;" /></a></p>
<p>Like the <a href="http://www.w3.org/TR/html5/scripting-1.html#attr-script-defer">defer and async</a> attributes, there is a general use case for document authors to be able to tell the browser that a piece of javascript will impact the loading of assets and thus should be executed before parsing begins. There are probably even use cases that have nothing to do with asset downloading where telling the browser to execute javascript before parsing would be beneficial.</p>
<p>One of the other suggestions for solving this was for browsers to standardize on how they load assets. I don’t like that idea because it prevents browsers from experimenting on ways to parse pages and load assets more quickly.</p>
<p>If authors explicitly tell the browser when javascript loading matters (preparse, defer or async), it allows browser makers to experiment freely in other situations.</p>
<h3>Long run solution: improvements to img tag</h3>
<p>In the long run, I don’t like the idea that solutions require javascript. Images are content or presentation which means it should be possible to handle it with HTML and CSS alone.</p>
<p>Therefore, I would like to see one of these two improvements to the img tag:</p>
<code style="white-space:pre;margin:10px 0 10px 0;">
&lt;img alt="butterfly"&gt;
  &lt;source src="butterfly-small.png" media="max-device-width:480px" /&gt; 
  &lt;source src="butterfly-large.png" media="min-device-width:481px" /&gt;
&lt;/img&gt;

</code>
<p style="font-size:x-small">Modified from <a href="http://twitter.com/bryanrieger">Bryan</a> and <a href="http://twitter.com/stephanierieger">Stephanie Rieger</a>’s <a href="http://www.slideshare.net/bryanrieger/rethinking-the-mobile-web-by-yiibu">Rethinking the Mobile Web</a> talk.</p>
<p>This is my preferred option, but I’m unclear on how older browsers would handle an image tag that contains child elements.</p>
<p><a href="http://twitter.com/#!/_crossdiver">Isaac Lewis</a> put together a <a href="http://ikelewis.com/the-future.html">test page</a> using this style of markup. It would be great to collect some feedback on old browser support to see if it works or causes problems.</p>
<p>If that won’t work because of legacy browsers, the following variation <a href="http://old.nabble.com/add-html-attribute-for-%22responsive-images%22-td32324865.html">proposed</a> by <a href="http://twitter.com/novolodesign">Anselm Hannemann</a> should:</p>
<code style="white-space:pre;">
&lt;img src="http://cdn.url.com/img/myimage_xs.jpg" 
     media-xs="(min-device-width:320px and max-device-width:640px)" 
     media-src-xs="http://cdn.url.com/img/myimage_xs.jpg"  
     media-m="(min-device-width:640px and max-device-width:1024px)" 
     media-src-m="http://cdn.url.com/img/myimage_m.jpg"  
     media-xl="(min-device-width:1024px)" 
     media-src-xl="http://cdn.url.com/img/myimage_xsl.jpg" 
/&gt;

</code>

<h3>Why not headers?</h3>
<p>I would love the browser to send more data to the server about the device making the request, but I don’t think servers should be necessary for the image tag to work in a responsive design.</p>
<p>I also think there is a decent chance that screen size is just the first of many headers we’d like the browser to send along. I don’t want to open up pandora’s box, but it would be nice to get something that felt more like a comprehensive solution instead of a bandaid.</p>

<h3>Why not a different, progressive image format?</h3>
<p>I’d love this, but feel wholly unqualified to judge what it would take. I’m not sure how long something like that would take to implement and what sort of patent minefield might lie there.</p>

<h3>So let’s start with the preparse attribute</h3>

<p>Unless someone points a major flaw with the preparse idea, I’m going to submit it as a feature request to the appropriate people to get the ball rolling.</p>
<p>Which reminds me, does anyone know where I should start? <img src='http://www.cloudfour.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/preferred-solutions-for-responsive-images/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>When is Mobile Safari not Mobile Safari?</title>
		<link>http://www.cloudfour.com/when-is-mobile-safari-not-mobile-safari/</link>
		<comments>http://www.cloudfour.com/when-is-mobile-safari-not-mobile-safari/#comments</comments>
		<pubDate>Wed, 12 Jan 2011 22:36:06 +0000</pubDate>
		<dc:creator>Jason Grigsby</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mobile safari]]></category>
		<category><![CDATA[safari]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=1219</guid>
		<description><![CDATA[When it is AppleCoreMedia. Let me explain. I wrote recently about a quiz that we built that included HTML5 audio files. In addition to the volume problems already discussed, we encountered intermittent issues where the audio either would not play or would play much later than it should. For the quiz, we preloaded the HTML5 [...]]]></description>
			<content:encoded><![CDATA[<p>When it is AppleCoreMedia. Let me explain.</p>
<p>I <a href="http://www.cloudfour.com/iphones-magical-volume-buttons/">wrote recently about a quiz</a> that we built that included HTML5 audio files. In addition to the volume problems already discussed, we encountered intermittent issues where the audio either would not play or would play much later than it should.</p>
<p>For the quiz, we preloaded the HTML5 audio file via javascript. To make sure that the file was set up for caching, we set far future expires headers as well as making sure the file was sufficiently small.</p>
<p>Whenever we displayed the screen that told the user whether or not they got a question correct, we play the preloaded audio file. Most of the time this worked flawlessly, but occasionally the iPhone would play the sound long after the results screen was displayed or not play the file at all.</p>
<p>That&#8217;s when things started getting weird. We watched the log files and started seeing some odd behavior. Here&#8217;s what we saw:</p>
<pre style="border:1px solid #e1e1e1;padding:5px;background:#ffe;font-size:small;overflow: scroll;">
"GET /trivia HTTP/1.1" 200 2346 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /media/quiz_wrong.m4a HTTP/1.1" 206 337 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /media/quiz_right.m4a HTTP/1.1" 206 337 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /trivia.css HTTP/1.1" 200 988 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
</pre>
<p>See what happened there? <strong>The user agent string changed from the normal Mobile Safari one (AppleWebKit) to one I hadn&#8217;t seen before: AppleCoreMedia</strong>.</p>
<p>It makes sense when you think about it. All video and audio playback gets handled by a system component. That component is responsible for downloading the asset. Ergo, the user agent string should change accordingly.</p>
<p>Surprisingly, this is true on desktop Safari as well. The equivalent user agent string is &#8220;Apple Mac OS X v10.6.6 CoreMedia v1.0.0.10J567.&#8221;</p>
<h3>AppleCoreMedia Caching</h3>
<p>On its own, the change from Mobile Safari&#8217;s user agent string to AppleCoreMedia&#8217;s user agent string would hardly be worth noting. But we were encountering problems with the sound not playing all of the time.</p>
<p>Because we noticed the sound problems happened more frequently on 3G than on WiFi, we started to suspect network issues and wondered if the audio file that we preloaded was getting cached properly. Here&#8217;s what we found in the logs:</p>
<pre style="border:1px solid #e1e1e1;padding:5px;background:#ffe;font-size:small;overflow: scroll;">
"GET /trivia HTTP/1.1" 200 2346 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /media/quiz_wrong.m4a HTTP/1.1" 206 337 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /media/quiz_right.m4a HTTP/1.1" 206 337 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /trivia.css HTTP/1.1" 200 988 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /media/quiz_wrong.m4a HTTP/1.1" 206 5494 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /media/quiz_right.m4a HTTP/1.1" 206 2597 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /js/trivia.js HTTP/1.1" 200 2618 -" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /media/quiz_right.m4a HTTP/1.1" 206 337 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /media/quiz_wrong.m4a HTTP/1.1" 206 337 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /media/quiz_right.m4a HTTP/1.1" 206 2597 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /media/quiz_wrong.m4a HTTP/1.1" 206 5494 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
</pre>
<p>All of that occurs before the first quiz answer is submitted so it is only in relation to preloading the audio.  The files get downloaded multiple times. Lest you think this is simply http chunking per the 206 responses, here are the file sizes:</p>
<pre style="border:1px solid #e1e1e1;padding:5px;background:#ffe;font-size:small;overflow: scroll;">
-rw-r--r-- 1 cloudfour psacln 2256 Dec 10 17:33 quiz_right.m4a
-rw-r--r-- 1 cloudfour psacln 5153 Dec 10 17:33 quiz_wrong.m4a
</pre>
<p>Before the audio file is ever played, AppleCoreMedia has downloaded 11,662 bytes for quiz_wrong.m4a. At 5153 bytes, the source file is less than half of the total bytes download.</p>
<p>When we could replicate the audio problems, we would find that the server would return a 304 response to AppleCoreMedia letting it know that the m4a had not been modified, but then AppleCoreMedia would go ahead and download it anyways. Of course, this behavior was inconsistent making it difficult to troubleshoot.</p>
<p>To try to narrow down the behavior, I created a simple page with links to m4a and mp3 files. I didn&#8217;t do any HTML5 audio embedding and didn&#8217;t include javascript. The page was as vanilla as can be. The test file size was 30,196 bytes. Clicking on the m4a link with a clear cache had the following result:</p>
<pre style="border:1px solid #e1e1e1;padding:5px;background:#ffe;font-size:small;overflow: scroll;">
"GET /examples/applecoremedia/trailer_iphone_sound/ HTTP/1.1" 200 653 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /examples/applecoremedia/trailer_iphone_sound/trailer_iphone_trimmed.m4a HTTP/1.1" 200 30551 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /examples/applecoremedia/trailer_iphone_sound/trailer_iphone_trimmed.m4a HTTP/1.1" 304 233 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /examples/applecoremedia/trailer_iphone_sound/trailer_iphone_trimmed.m4a HTTP/1.1" 206 22410 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /examples/applecoremedia/trailer_iphone_sound/trailer_iphone_trimmed.m4a HTTP/1.1" 304 233 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /examples/applecoremedia/trailer_iphone_sound/trailer_iphone_trimmed.m4a HTTP/1.1" 206 22410 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
</pre>
<p>This is even more confusing than the last example. The full m4a file is first downloaded by Mobile Safari. Then AppleCoreMedia asks the server if the file has been modified and is told by the server that it hasn&#8217;t. AppleCoreMedia then ignores this information and proceeds to download the file. Then it repeats the process for good measure.</p>
<p>And despite setting far future expires headers for everything, the next time you play the m4a file, the same process is repeated.</p>
<p>Because of the issues we had previously had with short audio files, I decided to try a longer video file to see what it would do. Again, I set up a simple page and linked to the video file. The video file was 3,995,176 bytes (3.8MB).</p>
<pre style="border:1px solid #e1e1e1;padding:5px;background:#ffe;font-size:small;overflow: scroll;">
"GET /examples/applecoremedia/trailer_iphone/ HTTP/1.1" 200 729 "http://www.cloudfour.com/examples/applecoremedia/" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /examples/applecoremedia/trailer_iphone/trailer_iphone%20-%20iPhone.m4v HTTP/1.1" 206 386 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /examples/applecoremedia/trailer_iphone/trailer_iphone%20-%20iPhone.m4v HTTP/1.1" 200 70500 "-" "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5"
"GET /examples/applecoremedia/trailer_iphone/trailer_iphone%20-%20iPhone.m4v HTTP/1.1" 206 71910 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /examples/applecoremedia/trailer_iphone/trailer_iphone%20-%20iPhone.m4v HTTP/1.1" 206 386 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
"GET /examples/applecoremedia/trailer_iphone/trailer_iphone%20-%20iPhone.m4v HTTP/1.1" 206 3995571 "-" "AppleCoreMedia/1.0.0.8C148 (iPhone; U; CPU OS 4_2_1 like Mac OS X; en_us)"
</pre>
<p>Mobile Safari still downloads some part of the m4v file, but it isn&#8217;t the full file size (70500 bytes). It is unclear what it does with this data chunk nor why it appears to only be part of the data, but the server reports a 200 response instead of 206.</p>
<p>The next time the video is played, the same pattern repeats. Nothing appears to be cached. Based on <a href="http://www.yuiblog.com/blog/2010/07/12/mobile-browser-cache-limits-revisited/">previous research into iPhone 4 cache sizes</a>, I would have expect even the 3.8MB video to get cached.</p>
<h3>What I Expected to See</h3>
<p>To illustrate what I expected to see, I ran with my simple audio file test in Firefox. The only change I made was to use an mp3 file instead of an m4a.</p>
<pre style="border:1px solid #e1e1e1;padding:5px;background:#ffe;font-size:small;overflow: scroll;">
"GET /examples/applecoremedia/trailer_iphone_sound/ HTTP/1.1" 200 653 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3"
"GET /examples/applecoremedia/trailer_iphone_sound/trailer_iphone_trimmed.mp3 HTTP/1.1" 200 28185 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3"
</pre>
<p>No matter how many times I load the mp3 file and then hit the back button to the web page containing the link, neither the web page nor the mp3 file were downloaded again. They had been successfully cached.</p>
<h3>What does all this mean?</h3>
<p>I wish I knew. For our project, it meant that we could not consistently ensure that the audio file would play at the right moment when the message was displayed on the screen letting the user know if they had got the question right or not. This issue combined with the volume issues caused us to remove the feature.</p>
<p>For consumers using iPhones, it appears to mean that every time you watch a video or play an audio file, that your phone is going to download it again. This makes for a slower experience and puts a seemingly unnecessary burden on the carrier network.</p>
<p>For developers, it is important to realize that video and audio playback in Mobile Safari is not handled by Mobile Safari even if you&#8217;re controlling it via javascript and the system media player is never visible. Everything you&#8217;ve learned about how Safari and Mobile Safari handle the downloading of assets doesn&#8217;t apply when AppleCoreMedia is doing the work instead of Safari.</p>
<p>Finally, this is just one more clue about how mobile is still frontier land. Even something that seems simple like a quiz that plays sounds can bump up against the boundaries of what we know about how mobile browsers work and what they can reliably do.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/when-is-mobile-safari-not-mobile-safari/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>JavaScript GZIP Compression in WordPress: What&#8217;s Possible and what Hurts</title>
		<link>http://www.cloudfour.com/javascript-gzip-compression-in-wordpress-whats-possible-and-what-hurts/</link>
		<comments>http://www.cloudfour.com/javascript-gzip-compression-in-wordpress-whats-possible-and-what-hurts/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 21:22:20 +0000</pubDate>
		<dc:creator>Lyza Gardner</dc:creator>
				<category><![CDATA[Blogs and Social Media]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=609</guid>
		<description><![CDATA[WordPress 2.8 introduced some constants and bits and bots that nominally make certain kinds of compression of JavaScript and CSS possible. This post looks at JavaScript compression and explains what is possible, and what is very, very hard. In a nutshell, with a bit of tweaking, you can GZIP and concatenate the scripts that come [...]]]></description>
			<content:encoded><![CDATA[<p>WordPress 2.8 introduced some constants and bits and bots that nominally make certain kinds of compression of JavaScript and CSS possible. This post looks at JavaScript compression and explains what is possible, and what is very, very hard.</p>
<p>In a nutshell, with a bit of tweaking, you can <strong>GZIP and concatenate the scripts that come packaged with WordPress</strong>. GZipping and concatenating anything else&#8211;plugin scripts or scripts in your own theme&#8211;is not currently supported in any obviously sane way (using WP&#8217;s WP_Scripts management class anyway).</p>
<p>I&#8217;m going to give away the ending to save you some time:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">add_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wp_enqueue_scripts'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'lyza_force_compress'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">function</span> lyza_force_compress<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$compress_scripts</span><span style="color: #339933;">,</span> <span style="color: #000088;">$concatenate_scripts</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$compress_scripts</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$concatenate_scripts</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ENFORCE_GZIP'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
    <span style="color: #666666; font-style: italic;">/* enqueue your scripts here */</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Putting the above in your functions.php file <em>may</em> result in insanely good compression on your subsequently-enqueued JavaScript files. I say <em>may</em> because GZIP is one of those fidgety server-side things that varies from hosting provider to hosting provider. I tested this approach on two vastly different environments and had good success, but as always with these things, YMMV.</p>
<p>While this may look rather silly and simple, figuring out exactly which constants and globals to set and when to set them took me just about forever. </p>
<p>The most important thing to note is that <strong>this only works on scripts that come pre-packaged with WordPress and are listed in the wp_default_scripts() function in wp-includes/script-loader.php</strong>. This is slightly irritating.</p>
<h3>When it Does Work</h3>
<p>The above will concatenate and GZIP all of the applicable enqueued JavaScript into a single request, served out through the wp-admin/load-scripts.php script. </p>
<ul>
<li>By &#8220;applicable&#8221;, I mean scripts listed in wp-includes/script-loader.php in the wp_default_scripts() function.</li>
<li>If you have applicable JavaScript in both the head and the foot, you will end up with two script src tags. If everything is in the foot (or the head), you&#8217;ll get one tag. You not only get GZipping, you get fewer HTTP requests! Yay!</li>
<li>JavaScript in plugins and your own theme won&#8217;t get concatenated and GZipped in this approach, but it certainly doesn&#8217;t break it.</li>
</ul>
<p>In testing, the following:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">    wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'thickbox'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'scriptaculous'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'editor'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Went from:</p>
<p>10 requests, 310kB</p>
<p>to</p>
<p>2 requests, 90kB</p>
<p>with the activation of the above function. Nice! I got two requests because the above enqueueing puts stuff in both the head and the footer.</p>
<p><strong style="font-size:1.5 em; border: 1px solid #ccc; padding: 1em;width:100%">That&#8217;s a 340% improvement on filesize alone.</strong></p>
<h3>Why Won&#8217;t It Work for All JavaScript?</h3>
<p>Because there are no, nada, zilch, none hooks for making it do so without doing some deep surgery and writing a plugin. It boils down to a couple of places in code:</p>
<p>From wp-includes/class.wp-scripts.php in the do_item() function:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>100
101
102
103
104
105
106
107
108
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">in_default_dir</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$srce</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">print_code</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">print_scripts_l10n</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">concat</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$handle</span>,&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">concat_version</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$handle</span><span style="color: #006699; font-weight: bold;">$ver</span>&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ext_handles</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$handle</span>,&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ext_version</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$handle</span><span style="color: #006699; font-weight: bold;">$ver</span>&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>To get the built-in concatenation and GZIPped delivery, it is necessary that the if statement here evaluate true. I won&#8217;t explain the nitty gritty unless you really want me to. </p>
<p>So, my first approach was to add paths to the $wp_scripts->default_dirs Array to add entries for my theme&#8217;s scripts and my plugin dir&#8217;s scripts. Big fat fail.</p>
<p>The reason is that the actual file &#8212; <strong>wp-admin/load-scripts.php</strong> &#8212; that serves up the concatenated, zipped JavaScript is a standalone script. I imagine that this is both for security and for performance. It does not have the complement of WordPress constants and hooks that we are accustomed to. In fact, it is <strong>completely and absolutely unpluggable</strong> (unless I missed something). It only includes the files that define the WP_Scripts and WP_Dependencies classes, and utility functions for those. It does not include any theme- or plugin-level items.</p>
<p>And it does something that completely shuts down the game. It instantiates a new, clean WP_Scripts object and then calls wp_default_scripts(). </p>
<p>If you&#8217;ll recall, the WP_Scripts object in a normal WordPress request is a global singleton that manages all of the enqueued scripts. By creating a new instantiation, the load-scripts.php script has obliterated any notion of any enqueued scripts. Further, the wp_default_scripts() function is a hard-coded list of the JavaScript files that WordPress comes packaged with. While this function nominally triggers the &#8216;wp_default_scripts&#8217; action, this is not usable here because no files are getting included in which I could take advantage of that hook. Further, it redefines do_action() and other API functions as blank functions that do nothing. </p>
<p>The load-scripts.php file then iterates through the requested JavaScript handles (comma-delimited GET) and sees if it recognizes them from the wp_default_scripts() list. As anything that&#8217;s in your own theme or in a plugin won&#8217;t be in this list, FAIL. </p>
<p>Though I see some possible options for me in the writing-a-plugin realm, I also sadly see that it would replicate functionality and am highly curious as to what the WordPress developers had in mind here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/javascript-gzip-compression-in-wordpress-whats-possible-and-what-hurts/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Getting all JavaScript into the Footer in WordPress? Not so fast, Buster!</title>
		<link>http://www.cloudfour.com/getting-all-javascript-into-the-footer-in-wordpress-not-so-fast-buster/</link>
		<comments>http://www.cloudfour.com/getting-all-javascript-into-the-footer-in-wordpress-not-so-fast-buster/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 20:26:02 +0000</pubDate>
		<dc:creator>Lyza Gardner</dc:creator>
				<category><![CDATA[Blogs and Social Media]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=591</guid>
		<description><![CDATA[Warning: Technical WordPress post ahead! Overview: Really Getting JavaScript Into the Footer Quoth the WordPress Version 2.8 feature list: &#8211; Improvements to the script loader: allows plugins to queue scripts for the front end head and footer, adds hooks for server side caching of compressed scripts, adds support for ENFORCE_GZIP constant (deflate is used by [...]]]></description>
			<content:encoded><![CDATA[<p><br />
Warning: Technical WordPress post ahead!</p>
<h3>Overview: Really Getting JavaScript Into the Footer</h3>
<p><strong>Quoth the WordPress Version 2.8 feature list:</strong></p>
<blockquote><p> &#8211; Improvements to the script loader: <strong>allows plugins to queue scripts for the front end head and footer</strong>, adds hooks for server side caching of compressed scripts, adds support for ENFORCE_GZIP constant (deflate is used by default since it&#8217;s faster)
</p></blockquote>
<p>At the time, I thought <em>Wow, cool. When I have time, I&#8217;ll investigate that</em> and then immediately forgot about it for a few months. During RSS-coffee-breaks I read <a href="http://lesterchan.net/wordpress/2009/01/26/loading-javascript-in-footer-in-wordpress-28/">Lester Chan&#8217;s post</a> about how to put JavaScript in the footer (sounds easy enough!) and <a href="http://wpdevel.wordpress.com/2009/02/06/script-loader-updates/">Andrew Ozz&#8217;s post</a>, which left me coated with an intense and foolish optimism about compression.</p>
<p><strong>What I aim to do in this post</strong> &#8212; part one of a series of three if I find time to investigate the second and third pieces &#8212; is <strong>explain why it&#8217;s not as easy as you&#8217;d expect to get some scripts (specifically scripts that come with WordPress by default) into the footer, and how you can make it happen.</strong></p>
<p>If you&#8217;re <strong>in a hurry, you can skip to the Summary section at the end of the post</strong>.</p>
<h3>WP JavaScript Inclusion: Header vs. Footer</h3>
<p>What I read had me believe that it is falling-off-log easy to put all WordPress JavaScript in the footer. If you are trying to include a piece of JavaScript, say, in a plugin, that WP has not previously known about, it <em>is that easy</em>. But woe if you try this on certain scripts that come packaged with WordPress.</p>
<p>Let&#8217;s take a look at the functions that are involved in letting WordPress know that you want to use a given piece of JavaScript.</p>
<p>These are taken from wp-includes/functions.wp-scripts.php. </p>
<h4>wp_register_script() and wp_enqueue_script()</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Register new JavaScript file.
 *
 * @since r16
 * @see WP_Dependencies::add() For parameter information.
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> wp_register_script<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #000088;">$src</span><span style="color: #339933;">,</span> <span style="color: #000088;">$deps</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ver</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$in_footer</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_a</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'WP_Scripts'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
		<span style="color: #000088;">$wp_scripts</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WP_Scripts<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #000088;">$src</span><span style="color: #339933;">,</span> <span style="color: #000088;">$deps</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ver</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$in_footer</span> <span style="color: #009900;">&#41;</span>
		<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add_data</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'group'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Enqueues script.
 *
 * Registers the script if src provided (does NOT overwrite) and enqueues.
 *
 * @since r16
 * @see WP_Script::add(), WP_Script::enqueue()
*/</span>
<span style="color: #000000; font-weight: bold;">function</span> wp_enqueue_script<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #000088;">$src</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$deps</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ver</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$in_footer</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_a</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'WP_Scripts'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
		<span style="color: #000088;">$wp_scripts</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WP_Scripts<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$src</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$_handle</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$handle</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_handle</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$src</span><span style="color: #339933;">,</span> <span style="color: #000088;">$deps</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ver</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$in_footer</span> <span style="color: #009900;">&#41;</span>
			<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add_data</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_handle</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'group'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enqueue</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>As a theme developer, you may only ever have encounters with wp_enqueue_script(). But let&#8217;s look at what each of these functions does so I can then explain the issue.</p>
<p><strong>wp_register_script()</strong> tells WordPress about a script, but does not actually cause it to be included in a given page request. By default, WordPress registers a gripload of scripts that are then available to you, the theme hacker, when or if you should need them. A list of these can be found in wp-includes/script-loader.php in the wp_defalut_scripts() function. Highlights include jQuery, prototype, scriptaculous, etc., as well as extensions to those frameworks (e.g. jQuery UI). WordPress (via the WP_Scripts class, itself extended from WP_Dependencies) handles dependencies and makes sure that jQuery UI doesn&#8217;t get included without its necessary jQuery, if you should forget to enqueue jQuery itself or it gets enqueued after jQuery UI.</p>
<p><strong>wp_enqueue_script()</strong> tells WordPress, hey, I actually need this script, in this request. You may have seen or done something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This spools up jQuery and spits out a script tag to include the requested script. </p>
<p>In a lot of cases, it seems easy and straightforward to do this simple enqueue request. jQuery comes packaged with WP and is automatically registered for you, so you just have to hand the wp_enqueue_script() function one argument: $handle. </p>
<p>As a clever theme hacker, you may have noticed that the signature for wp_enqueue_script() and wp_register_script() changed in version 2.8 and this seems exciting. <strong>An $in_footer parameter was added:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">wp_enqueue_script<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #000088;">$src</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$deps</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ver</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$in_footer</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Totally psyched, you update your theme and use:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>And wait for the magic. RELOAD! Wait, maybe something&#8217;s cached. RELOAD! Wait, what? RELOADRELOADRELOAD.</p>
<p><strong>jQuery is still in the head.</strong></p>
<p>So you get irritable and you quit trying, or like me you spend a few hours deactivating all of your plugins and trying to figure out where the problem is. You notice that the same thing happens with other scripts that WP already knows about (that is, the scripts in wp_default_scripts()). Stubbornly, they won&#8217;t get out of your page&#8217;s head element.</p>
<p>Here&#8217;s why.</p>
<h3>Why WordPress Default JavaScripts Won&#8217;t Move to the Footer</h3>
<p>The crux is: <strong>if the script you are enqueueing has anything defined as a dependency in WordPress&#8217; wp_default_scripts() function, it will ignore your request to put it in the footer</strong> (I&#8217;ll provide a workaround shortly). </p>
<p>The reason for this is twofold. </p>
<h4>Dependency Handling and &#8220;Groups&#8221;</h4>
<p>Part of WordPress&#8217; dependency handling for scripts involves &#8220;groups&#8221;, the ins and outs of which I&#8217;ll leave as an exercise for an intrigued reader. In an oversimplification, it put scripts with dependencies (e.g. jQuery, Scriptaculous) in groups[0]. It explicitly puts scripts that depend on other scripts in groups[1]. The default behavior of both wp_register_script()  is to put a script in groups[0] if the $in_footer argument != true.</p>
<h4>How Groups Handling does Something Possibly Confusing</h4>
<p>OK, now check out this snippet from class.wp-scripts.php (do_item() method):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>85
86
87
88
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$group</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">groups</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$handle</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">in_footer</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$handle</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This piece of logic puts groups &gt; 0 into the footer. So <strong>that&#8217;s how WP decides to move things into the footer</strong>&#8211;it&#8217;s based on where the script is in the $wp_scripts->groups Array. </p>
<p>But here&#8217;s a potential pitfall in the wp_enqueue_script() function:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$src</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$_handle</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$handle</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_handle</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$src</span><span style="color: #339933;">,</span> <span style="color: #000088;">$deps</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ver</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$in_footer</span> <span style="color: #009900;">&#41;</span>
			<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add_data</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_handle</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'group'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$wp_scripts</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enqueue</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$handle</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>If you don&#8217;t give wp_enqueue_script() a $src (which you don&#8217;t have to provide do if the script has already been registered) for your $handle, it is going to enqueue it in whatever group it&#8217;s already registered in</strong>. So, when you do your little simple enqueue:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The entire part of the function where it would put it in the footer doesn&#8217;t execute because the if($src) test fails. And jQuery has already been registered&mdash;in groups[0].</p>
<h4>Possible Workaround</h4>
<p>I don&#8217;t like this but it works:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/wp-includes/js/jquery/jquery.js'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>jQuery is now in the footer.</strong></p>
<p>This does still appear to handle dependencies correctly, but I haven&#8217;t deeply tested. <strong>Also, there are some valid reasons to have some scripts, and possibly jQuery, in the head</strong>. This was just a demo.</p>
<h3>Getting JS into the Footer: Quick Summary</h3>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// This will NOT put jquery in the footer</span>
wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #666666; font-style: italic;">// But this will, if inelegant and circumventing abstraction</span>
wp_enqueue_script<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/wp-includes/js/jquery/jquery.js'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h3>For My Next Trick&#8230;Compression</h3>
<p>Really, this post was a red herring. I tripped into this oddity while investigating the second part of the WordPress 2.8 feature claim: <strong><em>adds hooks for server side caching of compressed scripts, adds support for ENFORCE_GZIP constant (deflate is used by default since it&#8217;s faster)</em></strong>. We&#8217;ll talk about that next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/getting-all-javascript-into-the-footer-in-wordpress-not-so-fast-buster/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Are CSS Sprites A Mobile Web &#8220;Worst Practice?&#8221;</title>
		<link>http://www.cloudfour.com/are-css-sprites-a-mobile-web-worst-practice/</link>
		<comments>http://www.cloudfour.com/are-css-sprites-a-mobile-web-worst-practice/#comments</comments>
		<pubDate>Wed, 27 May 2009 14:28:06 +0000</pubDate>
		<dc:creator>John Keith</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[CSS Sprites]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[YSlow]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=274</guid>
		<description><![CDATA[There&#8217;s an interesting article on mobiforge.com that talks about the pitfalls of using CSS sprites for mobile web content. While there are several reasons why sprites may not be a good idea, two stand out for me: CSS2 support is required for the necessary background positioning, and there may be longer term performance penalties associated [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s an <a href="http://mobiforge.com/developing/blog/widget-investigation-leads-a-worst-practice-discovery">interesting article</a> on mobiforge.com that talks about the pitfalls of using CSS sprites for mobile web content.  While there are several reasons why sprites may not be a good idea, two stand out for me: CSS2 support is required for the necessary background positioning, and there may be longer term performance penalties associated with using the layout engine for positioning on every page.</p>
<p>That performance aspect is something to think about.  The author states that it may be better to deliver a set of images once, paying a relatively small penalty for extra (cached, with long expiration) HTTP transactions, than to pay a layout engine penalty on every subsequent page rendering.</p>
<p>I can&#8217;t say for sure, but I can certainly imagine that some mobile devices are better than others when it comes to page rendering performance.  As one of the commenters in the article states, this &#8220;brings us back to the golden rule in mobile: know thy browser&#8230;&#8221;.  What works best in the desktop world may not be best in the mobile world.</p>
<p>The <a href="http://www.w3.org/2005/MWI/BPWG/Group/Drafts/BestPractices-2.0/ED-mobile-bp2-20091704.html#d1e8981">W3C says</a> that CSS sprites are a best practice for the mobile web so &#8212; this would seem to be a odds with that recommendation.  What do you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/are-css-sprites-a-mobile-web-worst-practice/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>High Performance Web Sites (CS193H)</title>
		<link>http://www.cloudfour.com/high-performance-web-sites-cs193h/</link>
		<comments>http://www.cloudfour.com/high-performance-web-sites-cs193h/#comments</comments>
		<pubDate>Mon, 18 May 2009 10:44:03 +0000</pubDate>
		<dc:creator>John Keith</dc:creator>
				<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=268</guid>
		<description><![CDATA[As many of you know, we&#8217;re fairly enamored with the YSlow techniques for understanding and evaluating web performance for web applications.  We have successfully used the information to improve the user-perceived performance for &#8220;traditional&#8221; websites and for mobile websites / applications.  We&#8217;ll be talking about more of those experiences in upcoming posts. In addition to [...]]]></description>
			<content:encoded><![CDATA[<p>As many of you know, we&#8217;re fairly enamored with the YSlow techniques for understanding and evaluating web performance for web applications.  We have successfully used the information to improve the user-perceived performance for &#8220;traditional&#8221; websites and for mobile websites / applications.  We&#8217;ll be talking about more of those experiences in upcoming posts.</p>
<p>In addition to the work we&#8217;ve done for our customers, we also like to promote good practices that everyone can follow.  Which leads me to today&#8217;s post.  I&#8217;ve recently finished re-reading <a href="http://cs193h.stevesouders.com/">the slides presented as part of the High Performance Web Sites course at Stanford University</a>.  These slides have been made available by Steve Souders and they provide a nice accompaniment to his book, <a href="http://www.amazon.com/dp/0596529309">High Performance Web Sites</a>.  The course also included guest lectures, and those slides have been made available to anyone who is interested in web front-end performance.  The guest slides are chock full of real world information from people who really know this stuff.</p>
<p>If you are a web developer, you should familiarize yourself with the <a href="http://developer.yahoo.com/performance/">Yahoo Exceptional Performance info</a> by reading their best practices list, reviewing the CS193H slides, and keeping the Souders book in front of you so you don&#8217;t forget to do it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/high-performance-web-sites-cs193h/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mobile Browser Test (One Year Later)</title>
		<link>http://www.cloudfour.com/mobile-browser-test-one-year-later/</link>
		<comments>http://www.cloudfour.com/mobile-browser-test-one-year-later/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 16:00:54 +0000</pubDate>
		<dc:creator>John Keith</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=260</guid>
		<description><![CDATA[Hey there. It&#8217;s been a year since we first opened our mobile browser concurrency test for people to use, so I thought I&#8217;d take a quick moment to thank everyone who has taken the test.  All 6,461 of you.  Yup, that&#8217;s how many individual test results we have thus far (and still counting&#8230;).  Those tests [...]]]></description>
			<content:encoded><![CDATA[<p>Hey there.</p>
<p>It&#8217;s been a year since we first opened our <a href="http://www.cloudfour.com/mobile/">mobile browser concurrency test</a> for people to use, so I thought I&#8217;d take a quick moment to thank everyone who has taken the test.  All 6,461 of you.  Yup, that&#8217;s how many individual test results we have thus far (and still counting&#8230;).  Those tests have yielded 1,572 unique user agents, of which 638 are unique mobile devices that have completed the test.  Wow.  Thanks everyone.</p>
<p>We&#8217;ve learned quite a bit from the data and we hope to see it put to use in some of the mobile device databases, such WURFL and Device Atlas.  While there are quite a few devices that support only one outstanding connection at a time, there are also quite a few newer devices that not only support several concurrent connections, but do so across multiple subdomains.  This is good news for mobile web sites that need to minimize page loading times.  We&#8217;ve also verified what we hoped to find &#8211; that most devices support http compression, which means there&#8217;s no reason not to gzip mobile content for mobile users.</p>
<p>If you would like to take a look at our first year results, trip on over to our <a href="http://www.cloudfour.com/mobile/summary.php">test summary page</a> and have a look around.  If you have any questions, please feel free to fire away.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/mobile-browser-test-one-year-later/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>We Have Disabled WP Super Cache</title>
		<link>http://www.cloudfour.com/we-have-disabled-wp-super-cache/</link>
		<comments>http://www.cloudfour.com/we-have-disabled-wp-super-cache/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 18:00:12 +0000</pubDate>
		<dc:creator>John Keith</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=253</guid>
		<description><![CDATA[To improve your WordPress performance we have previously advocated using the WP Super Cache plugin to enable pages served from a static cache.  This works quite well unless you are doing some form of content adaptation that is specific for the device accessing your site.  Like you might do for mobile devices. Some time after [...]]]></description>
			<content:encoded><![CDATA[<p>To improve your WordPress performance we have <a href="http://www.cloudfour.com/77/">previously advocated</a> using the WP Super Cache plugin to enable pages served from a static cache.  This works quite well <em>unless</em> you are doing some form of content adaptation that is specific for the device accessing your site.  Like you might do for mobile devices.</p>
<p>Some time after enabling the Super Cache plugin we noticed that our blog&#8217;s mobile adaptation had stopped working.  Mobile users were seeing the normal web view of blog posts and that was no good.  This was because the cache happened to contain a normal web view.  Interestingly enough, it could also have gone the other way to provide a mobile view of the blog to desktop web browsers.</p>
<p>So, we have turned the plugin off for the time being.  I have some ideas for working around this issue and if I manage to find some time I&#8217;ll give them a shot and let you know how it goes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/we-have-disabled-wp-super-cache/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mobile Device Detection Results</title>
		<link>http://www.cloudfour.com/mobile-device-detection-results/</link>
		<comments>http://www.cloudfour.com/mobile-device-detection-results/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 04:00:42 +0000</pubDate>
		<dc:creator>John Keith</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=244</guid>
		<description><![CDATA[In a previous post I presented the performance numbers for mobile device detection using WURFL and Device Atlas. Our numbers were generated on a data set consisting of 1,572 unique user agents we collected as part of our mobile device concurrency test.  At the time I was looking for information about the quality of our [...]]]></description>
			<content:encoded><![CDATA[<p>In a previous post I presented <a href="http://www.cloudfour.com/235/">the performance numbers</a> for mobile device detection using WURFL and Device Atlas.  Our numbers were generated on a data set consisting of 1,572 unique user agents we collected as part of our <a href="http://www.cloudfor.com/mobile/">mobile device concurrency test</a>.  At the time I was looking for information about the quality of our results &#8211; did we have accurate classification of mobile devices for the purposes of our test?  I unintentionally wandered into performance for a while, but now I&#8217;m back onto the quality thing.</p>
<p>Here, once again, are the results for processing 1,572 unique user agents:</p>
<table border="1">
<tbody>
<tr>
<td>Method</td>
<td>Time (seconds)</td>
<td>Mobile</td>
<td>Non-Mobile</td>
</tr>
<tr>
<td>WURFL Old API</td>
<td>1082</td>
<td>711</td>
<td>861</td>
</tr>
<tr>
<td>WURFL New API</td>
<td>20.8</td>
<td>1090</td>
<td>482</td>
</tr>
<tr>
<td>Device Atlas</td>
<td>1.2</td>
<td>527</td>
<td>1045</td>
</tr>
<tr>
<td>Mobile Device Detect</td>
<td>1.3</td>
<td>684</td>
<td>888</td>
</tr>
</tbody>
</table>
<p></p>
<p>As you can see, there are obviously some differences between results for each detection method.  Interestingly, both the old and new WURFL API use the same device database (wurfl.xml file), but yield considerably different results.  So, what&#8217;s going on here?  Is there a clear quality winner in the group?</p>
<p>For the time being, we are using the old WURFL API as our classifier.  The new WURFL API is giving us a <em>lot</em> of false positives &#8211; many different user agents are mapping to the wireless device &#8220;amoi_e72_ver1,&#8221; which could be some kind of fall-through condition.  It&#8217;s possible that I&#8217;m doing something wrong, but the API usage is pretty simple: instantiate a class and call a method with the user agent as a parameter.</p>
<p>Device Atlas is interesting to me and it&#8217;s quite possible we&#8217;ll be shifting to that for device detection.  It&#8217;s certainly <em>much</em> faster than WURFL in our environment.  While there are a few misses, there is really just one issue I&#8217;m seeing, and that may not be a real issue at all.  The Opera Mini user agents are not being classified as mobile.  Is this because we&#8217;re talking to a transcoder?  Or is it a mistaken classification?  I&#8217;m not sure, but the other methods all classify these user agents as mobile devices.  Take this user agent for example.  Should this be classified as a mobile device?  Device Atlas says no; WURFL says yes.</p>
<pre>Opera/9.50 (J2ME/MIDP; Opera Mini/4.0.10406/298; U; de)</pre>
<p>The mobile device detection script actually does a pretty good job.  Rather than use a comprehensive user agent database, this script looks for specific, known string fragments in the user agent string.  That&#8217;s also a bit of its undoing though.  For example, I&#8217;m seeing a bunch of false positives for user agents containing the word &#8220;Java.&#8221;  I think these false positives could be eliminated by <em>also</em> checking the HTTP_ACCEPT header for mobile content types.</p>
<pre>Java/1.6.0_05</pre>
<p>So the implication here is that you need to be aware that device detection is not guaranteed to be 100% accurate.  User agent strings are highly variable and non-standardized, so there&#8217;s a bit of artistry here.</p>
<h2>Resources</h2>
<ul>
<li><a href="http://wurfl.sourceforge.net">WURFL</a></li>
<li><a href="http://deviceatlas.com">Device Atlas</a></li>
<li><a href="http://detectmobilebrowsers.mobi/">Mobile Device Detection</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/mobile-device-detection-results/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Comparative Speed of WURFL and Device Atlas</title>
		<link>http://www.cloudfour.com/comparative-speed-of-wurfl-and-device-atlas/</link>
		<comments>http://www.cloudfour.com/comparative-speed-of-wurfl-and-device-atlas/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 02:00:03 +0000</pubDate>
		<dc:creator>John Keith</dc:creator>
				<category><![CDATA[Mobile Web and Services]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.cloudfour.com/?p=235</guid>
		<description><![CDATA[This has probably been done to death elsewhere, but since I&#8217;ve been playing around with WURFL and Device Atlas for mobile device detection, I thought I&#8217;d publish some comparative performance numbers. As part of our mobile browser concurrency test we needed to identify test results for mobile vs. non-mobile devices (we get a lot of [...]]]></description>
			<content:encoded><![CDATA[<p>This has probably been done to death elsewhere, but since I&#8217;ve been playing around with <a href="http://wurfl.sourceforge.net">WURFL</a> and <a href="http://deviceatlas.com">Device Atlas</a> for mobile device detection, I thought I&#8217;d publish some comparative performance numbers.</p>
<p>As part of <a href="http://www.cloudfour.com/mobile/">our mobile browser concurrency test</a> we needed to identify test results for mobile vs. non-mobile devices (we get a lot of traditional browsers using our &#8220;mobile&#8221; concurrency test!).  Because we did this as a post-processing step, we had a fair number of unique user agents &#8211; 1,572 &#8211; to classify.  We decided to use WURFL to identify mobile devices, but then also decided to perform that same classification via Device Atlas to see if we got similar results (more on that in a later post).  Not content to stop there, we decided to try both the old and new versions of WURFL, Device Atlas, <em>plus</em> <a href="http://detectmobilebrowsers.mobi/">a handy PHP mobile detection script</a>. </p>
<p>Here are the results for processing 1,572 unique user agents:</p>
<table border="1">
<tr>
<td>Method</td>
<td>Time (seconds)</td>
<td>Mobile Found</td>
<td>Non-Mobile Found</td>
</tr>
<tr>
<td>WURFL Old API</td>
<td>1082</td>
<td>711</td>
<td>861</td>
</tr>
<tr>
<td>WURFL New API</td>
<td>20.8</td>
<td>1090</td>
<td>482</td>
</tr>
<tr>
<td>Device Atlas</td>
<td>1.2</td>
<td>527</td>
<td>1045</td>
</tr>
<tr>
<td>Mobile Device Detect</td>
<td>1.3</td>
<td>684</td>
<td>888</td>
</tr>
</table>
<p></p>
<p>As you can see, performance and result quality vary significantly between the different methods.  Well, it&#8217;s tough to see the result quality here, but the <i>difference</i> between various results says that correctness is an issue.  The speed differences are tremendous though.  1,080 seconds is a long time to wait for results; 1.2 seconds on the other hand is quite pleasurable.  Now in all fairness, we didn&#8217;t do much to optimize the server performance, so it&#8217;s possible that WURFL will benefit from an in-memory caching strategy.  Perhaps we&#8217;ll see.</p>
<p>In my next post I&#8217;ll talk about how the results differ and the implications for relying on mobile device detection in your server code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudfour.com/comparative-speed-of-wurfl-and-device-atlas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 2.393 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-03 23:57:02 -->

