The way JavaScript is handled: A call to action
I’ve been doing a lot of thinking lately about the problems I repeatedly run into using JavaScript in browsers. While JavaScript has come a long way in terms of how we design and use it on the client, the way that browsers deal with JavaScript hasn’t changed fundamentally since Netscape 2.0 introduced it in the first place. Sure, we use a type
attribute instead of language
, but really nothing has changed and this has led to problems.
The number one problem I see is the way we are required to attach event handlers to elements. Look at how CSS works: the style definitions are loaded ahead of time and as an element appears on the screen that matches a particular pattern, that style is automatically applied. You don’t need to wait until the page has been completely loaded and then apply a style specifically to an element; the browser does this for you.
When we want to attach an event handler to an element, there are two ways to do it: 1) add an attribute in the HTML code, which is not recommended, or 2) add the event handler yourself using JavaScript. Since the first option is frowned upon because it too tightly couples the data and the behavior, we’re left with the second, which means you need to attach the event handler after the element is available. To do so, you’ll either use onload
or some alternative to DOMContentReady
. Though this decouples the layers better, there is a lag. It’s possible for the user to start clicking around on the page and have nothing happen because the event handlers haven’t been added yet. I think we can do better.
What if attaching events to elements worked just like assigning styles? What if you could tell the browser that a particular element should have a specific set of event handlers as soon as the element becomes available? This would free you from ever needing to call addEventListener()
or its equivalent; there would be no lag and you’d still maintain loose coupling between HTML and JavaScript. In fact, there’s already (non-standard) implementations of this, expressed in Microsoft’s DHTML Behaviors, which allow you to use the behavior
property in CSS to specify how elements should behave, and Mozilla’s XBL, which is how the standard elements of Firefox’s interface are defined (and may also be used in HTML). While neither of these are suited for building modern web applications (Microsoft’s implementation requires too many HTTP requests, Mozilla’s is far too abstract), this is where I believe JavaScript support in browsers needs to go.
Being able to specify behaviors in this way brings to light another problem with how browsers deal with JavaScript: they load each file synchronously, blocking other requests and preventing the page from rendering until the file has been completely downloade, parsed, and interpreted. Microsoft was nice enough to implement the defer
attribute on the <script/>
element, but that just defers the downloading and evaluation until after the page has been rendered. So basically, the options we have are either parse and evaluate now or parse and evaluate later, and neither of those is sufficient.
JavaScript files are loaded synchronously because of dependencies, file2.js may depend on stuff in file1.js to work properly. These dependencies need to be respected, but I think there’s a better way to do it. What if instead of blocking the browser while downloading a JavaScript file, we had a way of saying, “hey, this file just has behaviors that aren’t needed until the user starts interacting, so don’t worry about evaluating this code quite yet.”? Basically, make it work like style sheets currently work. Don’t stop the presses just to download and parse the file, keep going, download the file and add it to a global parse tree. Each time a new JavaScript file is loaded, fire off a request and then continue on, assembling the entire bunch of code behind the scenes as the page continues to load.
The Web has been around for a decent amount of time now and the art of building web applications has developed significantly enough that it’s time to start asking if the tools we currently have are good enough. Most people will say “no,” but can’t express what they’d like to change. So here I am, putting my foot down and saying this is what I’d not only like to see changed but also that I believe this has been a long time coming. We’ve become better JavaScript developers but the browsers remain as dumb as ever in how they handle JavaScript. It’s time for a change.