a retirement fund for your javascript
You ever find yourself feeling unreasonably protective of JavaScript? I do. For a long time, JS lacked a lot of sophistication. It was vulnerable to being trampled over by bigger, more powerful technologies like Java applets or Flash. There was nothing to really commend it to anyone who didn’t, for whatever crazy reason, already love it. Eventually it was able to do things for itself, but there were many years where it was pretty much defenseless and it sounds dramatic only in hindsight to say it wasn’t clear whether it was going to survive to maturity.
Maybe I just like underdogs, but I’ve rooted for JavaScript from the beginning. Probably unsurprising then that I was really pissed when I first encountered CoffeeScript. JavaScript had finally developed the power and utility people had mocked it for lacking, and now they were going to complain about its appearance? Bullshit. But lately I find that I don’t care as much about CoffeeScript et al.
JavaScript isn’t a little baby language anymore. It’s full-grown and it’s going places I never expected and it’s got fat arrows and other things I probably don’t even want to know about. Dropping the analogy, seriously, do you ever take a step back and consider how much it’s changed? JS used to be a very personal language. You didn’t share it with a compiler or a test suite and, if you were like me, you were the only person on your team who understood it and thus the only one who looked at it. It feels very public now, and I don’t mean once you put it on github. I mean that there are best practices, and they aren’t the secret handshake of a few embattled front-end developers stepping all the way out of the closet for the first time. Hell, sometimes they don’t even come from JavaScript developers. I repeated something I hadn’t fact-checked in nearly two years at work last week and some corrected me with a jsperf. For a minute, my unspoken reaction was, “It can’t be wrong, I learned that at a JS conference!” And then I realized that you don’t have to go to those conferences to understand things anymore, and that over the past year I’ve seen at least as many conference talks taking stock of state of JS as I’ve seen unveiling new or revelatory information.
As JS developers, we don’t really move JavaScript forward anymore. Browser vendors do that. Library authors who used to be the only people making our jobs possible without risk to our sanity are now just providing consistent abstractions around techniques that are built in, backward-compatible API calls that let our code remain the same while the logic moves from something written by us or developers like us to a part of the platform we’re writing for. And that’s what I actually want to talk about.
At SXSW this year, someone predicted that jQuery would not exist – at least, as we know it today – in two years. It was kind of one of those things where your mouth goes, “What?! That’s ridiculous!” while your brain goes, “Whoa, of course.” Obviously jQuery continues to improve, but in terms of the stuff that people desperately needed it for, it seems to me it’s been stable for some time. When I began my job last week I found out that there are a few parts of the site we’re in the process of upgrading from jQuery 1.3.2 to 1.6.2. I asked why we weren’t upgrading to the latest version. Part of the response was that the upgrade had begun when 1.6.whatever was the latest version. The other part was that the difference between the slightly-older and most-current versions didn’t seem compelling enough to justify starting over.
The idea of an optional jQuery upgrade is somewhat fascinating to me. People got stuck on 1.3, that’s understandable. There was a legitimate risk of things breaking, and how many sites had a full suite of regression tests at that point? But when did it become an option to not upgrade for lack of perceived value instead of threat of destruction? I don’t know, but I feel like it was recently. And although I think the changes since jQuery 1.6.2 are pretty fucking slick, I have to agree that the world isn’t going to end if we don’t upgrade immediately, or even if we never do.
My impression is that we’re in a brief window right now where jQuery still has a brilliant team of people working on it, but is stable from the perspective of most users. The most advanced might care deeply about event delegation and the features of deferreds, but someone who merely wants a reliable cross-browser click handler probably doesn’t give a shit. And they no longer have to. jQuery and others solved the problem so well that we can all safely forget there was a problem. Unfortunately, I think that means once there are no more improvements to make to event handling and no more features to add to deferreds, the brilliant team will begin moving on to other projects. I think the same will happen to Backbone, and Socket.IO, and whatever goofy-ass transpiler is cool right now. The things we had to do manually moved into libraries and tools, and the things we needed libraries and tools for are moving into the browser. It’s just a matter of time.
So if you agree that the sky is very slowly falling, what do you do about it? Two things. First, you begin to insulate yourself. Second, you take an active role in making sure the things you need most survive as open-source software and don’t get tied to larger projects whose futures may not include the relevance they enjoy now.
I’ve been about insulating yourself from plugins for some time. That’s cause I worked for a company that had three different dialog plugins in use and getting them standardized was a pain in the ass. When one was discovered to lack some important feature, no problem, someone would download a different one, implement it on a new page with new site-wide CSS to make it appear similar to the old one, and now there would be two ways of creating a dialog. Clearly that’s fucking stupid. But many places settle for standardizing on one dialog plugin, or one UI library that contains a dialog widget, and leaving it at that. I think you should go a step further. Don’t rely on developers (present and future) to know that you use jQuery UI for everything except this one super-special dialog. Instead create a library namespaced with your site or company’s name and put everything under there. I don’t give a shit if CoolCo.dialog has a signature that matches the plugin’s exactly and contains only one line where you pass the plugin its arguments. Wrap everything up, put it in the same namespace.
Once all your shit is insulated from the tools you’re using, begin looking at the methods you rely on. Are you using jQuery selectors but only targeting cutting-edge browsers? Maybe that’s something you could replace with querySelectorAll. Is that necessary? Will it everything super fast? Is there a big risk that jQuery selectors suddenly become monstrously inefficient? Probably not. But, on the other hand, it protects you from Bizarro John Resig. Bizarro John Resig is a theoretical maintainer of the jQuery project who will emerge in the post-apocalyptic future of web programming and decide to rewrite the library to optimize it for WebGL, and remove everything else. When that happens, you will be glad you’re using CoolCo.qsa instead of the dollar sign.
To put it another way, there’s excellent broadly applicable code in jQuery now that – for the things the library’s known for – gets the job done remarkably well. Once jQuery reaches a point where you’re very excited about the features a segment of the code provides, freeze that method yourself by copying it into your code. When a change to that feature that you need comes along, swap the code out. If you’ve insulated yourself well, hopefully the way your library uses the functionality doesn’t have to change.
I can see that you think I’m totally crazy and living in the nineties and a bunch of other perjoratives. That’s fine. Copying and pasting code is bad, isn’t it? Well yes. But as we move toward a point where all the JavaScript developers are getting bored and antsy and making things like freaking CoffeeScript, it’s smart to begin thinking about where you plan to get off the bus. Cause mark my words, this bus is headed to Crazy Town. The obvious practical problems are solved. Solutions to the difficult and subjective architectural problems are cropping up all over the place and converging on a few different philosophies. Eventually the geniuses of JavaScript are going to have nothing more amusing to do than make shrinkrays and giant homicidal robots, and you’re still just going to want your selectors to work in Chrome 1643 the way they did in Chrome 18. You see what I’m saying?
So in addition to building a fortress to protect you from the giant robots, there was a second point, and this is about avoiding copying and pasting wherever possible. Let’s go back to dialogs. You know what’s awesome about jQuery UI? It’s modular. If you just want dialogs, you can just get dialogs. We need everyone to do that. We need the pieces. Instead of downloading a package of everything including the kitchen sink we need modules. I think about this a lot when working on node stuff. Node lacks many things that are very monolithic. A lot of people are annoyed by this. The more I think about it, the more I like it. Your application should be written to run your application. There’s a new version of node? Of course there is, it’s Tuesday. Does it give you anything you need? No? Fuck it. Wait until you have a reason to move. More importantly, if a project progresses in such a way that it’s introducing dependencies that aren’t relevant for your app, consider whether it’s appropriate for you to maintain a fork without the dependencies that provides a subset of the functionality.
I feel kind of awful saying these things, but I believe them. It sounds like I’m saying write JavaScript that’ll live on a mainframe in a basement. That’s because that’s what I’m saying. Your application will either die or it will live on a mainframe in the basement. That field ain’t gonna stay green forever. Eventually your JavaScript is going to get old. Somebody should start planning for its future.

April 9th, 2012 at 10:28 am
Funny I was just working on getting ride of legacy dialog in an application with three solutions to overlays/dialogs/lightbox etc. Question, It seems to me that you are not suggesting to copy and paste every feature you want into your own codebase, but rather adding a facade into your own application that maps those desirable features to a method on your own namespace, e.g. MyCo.Deferred, MyCo.Callbacks etc. Recently I pulled these to pieces of functionality out of jQuery to use with Zepto and set up a facade to map the objects into my application’s codebase. Seems fairly easy to switch between Zepto / jQuery as long I keep references to the objects I need on my own namespace. I’m curious have you any opinion on ender.no.de ? -Bill
April 9th, 2012 at 10:34 am
@Bill – Yeah, I’m definitely not saying go out and starting copying+pasting everything. Just trying to express my sense that we as developers need to begin weening ourselves off the idea that a library is going to solve all of our problems forever just because it does right now. I’ve looked at ender, but I’ve yet to use it. For right now, my approach is still to use a single library and roll-my-own for whatever it doesn’t contain. But my goal is to have more discipline around adding that facade.
April 10th, 2012 at 2:25 pm
I’m less experienced with the history of jQuery, so this may be ill-informed, but: I think (hope) what we’ll see is a continuation of the thinking that gave us jQuery in the first place. That’s a hallmark of maturity in a developer community.
(I’m going out on a limb with this counterargument, because HTML5 contains loads of things that most people who don’t understand semantic or multiplatform development won’t use, and will continue structuring their pages like it’s 2002, because right now that still works. So, one might say that the W3C made another misstep in building in a bunch of speculative features that will go the way of the marquee tag. I don’t agree with that idea. So! Counterargument!) HTML5 is *also* the product of most of the web dev community balking at the state of HTML4. We demanded a toolset that was better suited for what we hoped to accomplish. We got it. jQuery’s existence is another success story, as I understand it: a small set of developers responded to demand for change, and change happened.
We’re going to see this real soon now with media queries, I think: their format is unsustainable. It is hacky and awful. Writing them makes me cringe. Something else will be the media targeting hotness in a year or less. Dependence on whatever the toolchain is will not be the problem, because the tools are iterable — we can keep demanding (and contributing to the development of) better ones. Having to go back to our code that we wrote a year ago and decide whether to gut it or rewrite it will be the problem. I would argue very strenuously against duplicating and freezing library code out of a belief that it will make your future code perform as you like. Remaining vocal and influential on the tool-development community seems like a way more responsible practice.
April 10th, 2012 at 11:06 pm
@Ari – It’s interesting that you feel that way about media queries. Issues aside, they certainly provide a lot more power than we’ve ever gotten from CSS before. And to me they seem much less hacky than the JavaScript techniques that preceded them. At any rate, I’m in favor of contributing to the development of better tools. I just think it’s not a bad idea to put a layer in place in case your contributions aren’t the direction a tool is heading.
April 24th, 2012 at 1:44 pm
I was just talking to the dev team I work on about this. The web community wants a native browser experience, but most of us aren’t learning all the awesome things that browser vendors are trying out. Instead, everyone is content with saying they know javascript after learning framework X.
Though I do believe that frameworks will always serve as an extension to native behavior and as javascript gets more powerful, so too will the frameworks, I agree with you that the role of frameworks is shifting. People need to learn what’s natively supported.
That said, awesome read. Thanks.
May 3rd, 2012 at 3:57 am
[...] Great rant on when to take your legacy code out back with a shotgun [...]
May 18th, 2012 at 11:55 am
I found your blog after harassing you about online chats on @jshotline. i am also renovating a house so of course I felt compelled to read your blog a bit! This is a fascinating post, and something I’ve given a good bit of thought to. I’ve upgraded jQuery in substantial projects occasionally, but almost never for new features, rather, for bug fixes. The explosion of minimalist frameworks speaks to the desires of the community: we want something to make our selectors work in old browsers and deal with some annoying stuff like “opacity” css and inconsistent DOM element method implementation. And probably an ajax wrapper.
Everything else? Not so much. jQuery has become the kitchen sink. I use an awesome library called “when.js” for promises and lots of other specific-purpose tools even though jQuery has a promises implementation. I’ve written my own stuff for a lot of UI things like tooltips, underscore-type utility functions, and so on. I’ve basically got my own framework, pieced together from my own work and the work of others. It’s not that well organized, but I like my own choices or implementations of each feature better than the ones included in jQuery. I did some work to make a jquery plugin I wrote zepto compatible a while ago, and found it took only about one screenful of polyfills to cover all the non-core jQuery methods I was using. I just don’t use most of jQuery.
I think the important part of the evolution is adoption of standards for how our code interoperates like CommonJS. The rise of Node has also done a lot to pave a path for this, and if people start adopting design standards that allow for trouble-free plugging of modules, things will be awesome. But I don’t think that a big, universal framework is in the future (what jQuery has kind of become) because one size just doesn’t fit all when you have a hundred different possible platforms your code could be running on.