Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

2010-01-23

HTML5 will lower the use of CDNs for delivering JavaScript

As Firefox 3.6 was released today, people have begun to use the async attribute for the script tag from HTML5. For those of you unaware of the new attribute, it tells the browser to execute the JavaScript that a script tag points to through its src attribute in an asynchronous manner. Now from my reading of the spec that should be asynchronously, but one at a time based on the order of the script tags are found in the doc. But if you play with Firefox 3.6 it becomes apparent that Mozilla disagrees with my interpretation as Firefox will begin executing the next async JavaScript file without waiting for the previous one to finish.

And this immediate execution is where things begin to make things interesting for using a CDN for JavaScript code. I don't know about some of you, but I use the Google AJAX Libraries
to get my copy of jQuery through their URL interface. This is great for me as it means the traffic is served by someone (i.e. free for me), Google's CDNs are fast, and there is a decent chance that others have used the CDN as well which lets the browser uses a cached copy of jQuery instead of fetching it again just for my web app. This means you don't concatenate jQuery in with your JavaScript code to get a single JavaScript file to serve, but my thinking (until now) has been that the perk of the browser already having a cached copy of jQuery was enough to not care about the potential separate HTTP request.

But you can't reliably use the async attribute with library code that subsequent JavaScript code depends on. In my case I use jQuery to execute JavaScript code once the page is loaded and rendered. When I put the async attribute on both the CDN-served jQuery code and on my own code, I was able on my local machine to occasionally trigger a race condition where my JavaScript code was executed before jQuery, triggering an error as $ was not defined yet. It was tough to trigger, but it definitely happened.

This means either you execute the CDN-served library code synchronously or you concatenate it with your code and serve that entire file asynchronously. The decision then becomes what gives you more benefit: possible faster downloading from a CDN plus cache hits but blocking JavaScript execution, or having to download from your servers but having fully asynchronous execution.

Now some of you might view this as a somewhat thin argument that CDNs serving JavaScript will get marginalized, and that's fair. But what I really think will impact it is offline web applications and the app cache. For a web application to work offline you define a cache manifest file which lists what URLs to cache, which URLs to hit a specific file if not online, and which ones should always go to the network no matter what. But at issue here is the fact that all listed URLs must follow the same-origin policy. This means that for you to serve up some JavaScript library while offline you need to have it hosted on your server to be able to list it in your cache manifest to get the benefits of an offline web app.

As people begin to look at offline web apps more and more I think it will be interesting to see how this impacts people's use of CDNs for stuff like JavaScript.

2009-10-14

I ♥ jQuery (UI)

I had this grand plan for a blog post comparing the various JavaScript GUI libraries, which in the end ended up being this blog post stating how I like jQuery UI. If you don't care about reading a "love letter" to jQuery UI, then you can stop reading now.

2009-08-18

Testing JavaScript code (and releasing realStorage 1.2)

The motivation behind the blog post is the release of realStorage 1.2. Two main things have been introduced in this version. One is helper functions which handle the (un)serialization of JSON objects into localStorage. This was the last idiom I have personally come across in my thesis work and thus ends (for now) my desire to add convenience functions to realStorage. After this I probably have the greatest desire to get a Gears back-end going for those browsers that do not support localStorage. But that will have to wait until Chromium on OS X begins to support the plug-in.

The other thing I added to this release was support for running the tests using JsTestDriver. This has stemmed from me trying to figure out how to do reasonable testing of both web applications and JavaScript libraries for my thesis work.

For JavaScript libraries I have been using QUnit, the testing framework for jQuery. It's worked out rather well. It is simple and has the proper concept of "sameness" for JS objects (if you have ever tried to do ``{a:42} === {a:42}`` you know what I mean). It also has XHR test support which is handy. Plus the jQuery code uses it so I can delve into their code to find example usage. And finally it has a nice HTML output page to look at failures. Tie that into the developer tools that come with WebKit browsers (e.g. Chrome and Safari) and my debugging situation is pretty good. I personally don't use Firebug as I have found it to be buggy too often and I like the WebKit developer tools. The only thing Firefox has going for it the Work Offline menu option which is handy when you are developing offline web apps.

But having an HTML page for testing a browser is a bit tiresome when you want to test against multiple browsers, which is where JsTestDriver comes in. It's a jar file that lets you "capture" multiple browsers to a server which then runs your tests on all of the captured browsers. Designed for continual integration testing, I find it handy to quickly test all of my tests on multiple browsers while I am developing. Plus there is a QUnit adapter in their svn repository which lets me code in QUnit while running it simultaneously in multiple browsers when I am not actively debugging.

For testing the view of a web app I have found WebDriver works well. There you write Java code (icky I know, but you can use other JVM languages) which uses the Selenium Java bindings and launches browsers to test them. What's neat is that it simulates key input and mouse clicking, so if you use Firefox for the testing browser you can watch the test enter text as it runs (albeit rather quickly).

So that's my JavaScript testing toolchain that I have come up with. So far it has worked out well and helped to keep me sane when dealing with JS.