Choosing a JavaScript library
Previously we looked at some objections to JavaScript libraries and some possible responses. Now it’s time to ask a bigger question: do you need a JavaScript library, and if so how should you go about choosing one? I’m not going to recommend any particular library, because I don’t think there’s such a thing as one-size-fits-all in web development, but I can list a few things which are useful to keep in mind when making these decisions. So let’s dive in.
Do you need a library?
No matter what language you’re writing, libraries all serve the same purpose: to provide common, reusable functionality and save you from writing lots of repetitive code. And no matter what language you’re writing, if you find yourself writing the same thing over and over, odds are you could use a library to help you out, whether it’s one that somebody’s already written or one that you write yourself and reuse.
When you’re writing JavaSript, it’s very easy to end up in just that situation; there are a number of common things you’ll need to do repeatedly, like attach listeners to events or fire off an XMLHttpRequest
, which will be pure misery if you have to write all the code for them each time you use them. For example, consider what’s needed to attach an event listener:
- You need to handle the different ways of attaching the listener.
-
You need to handle the scope in which the listener’s callback will execute (since the value of
this
will vary from browser to browser). - If you want access to the event’s target element you’ll need to handle the variations for that.
- If you want to prevent the default action for the event you’ll once again need to take care of cross-browser variations,
Writing that sort of thing just once is tedious. Writing it over and over again is a nightmare. So the natural solution should be some sort of reusable implementation which normalizes all the browser quirks and gives you a single interface to work with. And that’s precisely what libraries are for.
Of course, it’s possible to do a lot of things in JavaScript without XMLHttpRequest
or event listeners or a number of other things that most of the good libraries provide, and if you’re in that situation then you probably have no need for one. But most modern applications of JavaScript are heavily driven by events, AJAX, animations and the like, so sooner or later most people will need some sort of JavaScript library.
Do you need someone else’s library?
This is a trickier question; if you know enough about JavaScript, the DOM, XMLHttpRequest
and all the browser quirks, then you can probably write a nice little quite of common functionality for yourself. So why rely on someone else’s possibly-buggy code? I can think of a couple reasons:
- It saves time. There are lots of programmers who could implement most or all of the standard C libraries, but very few do; the standard C libraries have already been implemented for nearly every platform, so developing them again would be redundant and a waste of valuable time. Similarly, most of the common functionality needed for modern JavaScript programming has already been implemented and made available, so usually it’d be just as redundant and just as much a waste of time to write it all again.
- Third-party libraries are likely to be better than what you’d develop on your own. True, there are a few godlike individuals who can hammer out their own high-quality libraries of code, but most JavaScript programmers aren’t at that level. Meanwhile, there are plenty of libraries available which have significant user bases and so have more people spotting and dealing with bugs and deficiencies. That doesn’t mean these libraries will be perfect, but they’ll generally hold up better than the average programmer’s code.
So unless you have unique needs which rule out using any of the available JavaScript libraries, it’s probably best to use one of them instead of rolling your own.
What makes a good library?
It’s really tough to answer this in an objective fashion, because it’s not entirely an objective question; once you get beyond the basics, every programmer has slightly different needs and slightly different preferences, so there isn’t a “One True Library” out there which will be right for everyone.
As far as objectivity goes, there are a few things every good library has to have in order to be usable:
- A normalized event model, including attaching/removing listeners, automatic scope correction and access to the event itself.
-
A normalized wrapper around
XMLHttpRequest
, including the ability to specify callbacks to fire when the request finishes. - A set of normalized utilities for working with the DOM, especially for getting/setting styles and managing class names.
- Facilities for creating visual animations, whether pre-defined or custom, which handle cross-browser timing quirks.
Any library which doesn’t provide all four of these doesn’t really register on my radar; without this functionality I don’t think you can do modern JavaScript programming.
Subjectively, there are several other things I look for; missing one of them isn’t a deal-breaker by itself, but I’ll always gravitate toward libraries which meet most or all of these criteria:
- They feel natural for the language. JavaScript is an incredibly flexible language and it’s possible to do all sorts of things to make it “feel” more like some other language (typically, people want it to feel like Python or Ruby). Personally, I’ve never cared for that; blurring the distinction between JavaScript and the languages I use for server-side programming just makes context-switching between them more painful. The worst offenders here are libraries which try to make JavaScript’s object-orientation feel class-based instead of prototype-based; it’s fine to provide utilities for working with object prototypes, but no matter how hard you try you’re never going to make JavaScript be class-based. So just let it be.
-
They don’t wrap DOM methods for the sake of wrapping. Providing a wrapper when cross-browser variations make the real method hard to work with is fine, but I’ve seen too many libraries provide aliases to
getElementById
for no good reason; if I want it aliased to a shorter name, I’ll do that myself. Libraries which take it on themselves to do that for me are just adding unneeded overhead and polluting the namespaces I have to work with. -
Speaking of polluting namespaces: good libraries don’t do that. A JavaScript library should add one object to the global namespace, ideally with a name derived from that of the library. Adding more than one object to the global namespace is just asking for problems; sooner or later, somebody else is going to want to initialize an object named
Ajax
. - Closely related to that: good libraries get one object and keep all their code in it. Leaking code out into built-ins is once again asking for a headache. The Prototype folks learned that one the hard way so you wouldn’t have to.
- Good libraries are modular. There are tons of useful things that can go into a JavaScript library, but it’s rare that you need all of them at the same time; breaking the library up into tightly-focused modules lets me choose which bits I need at any given moment and keeps page weight under control. Modular code is also much easier to debug and maintain, so everybody wins with this one.
Again, these things are highly subjective; most of them are rooted in what I personally think constitutes good coding practice, and there’s room for lots of opinions on that topic. If you find yourself disagreeing with me on one or more of these points, just ignore them and move on; you’re probably not going to change my mind about them and I’m probably not going to change yours.
Oh, yeah, forgot about this…
There’s one other thing which can really make or break a JavaScript library, and it’s surprising how often it’s overlooked, because the same thing makes or breaks an awful lot of software in other fields: documentation. The greatest library in the world would fail if the only way to learn it was reading the code (and, in fact, it already has to a large extent). Some packages have managed to overcome this by way of lots of unofficial documentation — blog entries and the like — but there is absolutely no substitute for full, well-written documentation. The ideal, for me, consists of:
- High-level overviews of each part of the library, touching on key objects and methods.
- Practical examples showing how to handle common use cases.
- Full API documentation for everything in the library. JSDoc is both good and bad for this: good because it makes API docs stupidly easy to generate, and bad because people assume that API docs are all you need. Javadoc, which inspired JSDoc, has wrought much ill on the Java world for largely the same reasons.
- Comments throughout the code itself.
Pretty much everybody who’s developing a JavaScript library has dropped the ball on this; very few libraries manage even one or two of those points, and out of the teeming multitude of JavaScript libraries floating around today I’ve seen exactly one which manages to hit all four points with any kind of success. Maybe there are other splendidly-documented libraries out there, but I’ve yet to see them; most treat documentation like an afterthought. If you know of a library which does get the documentation right (and which isn’t produced by a company whose name rhymes with “wahoo”), let me know about it. If you’re a JavaScript library developer and you want some free publicity, bring your documentation up to snuff and point me at it. I’d really love to have to rescind this complaint at some point.
Go forth and choose
And that’s about all I’ve got on evaluating and choosing JavaScript libraries. I do have a favorite out of the current crop, and it shouldn’t be too hard for regular readers to figure out what it is, but I won’t push it on anybody; pick the tool that’s best at helping you do your job, use it and don’t fret about what someone else thinks.
Coming up sometime in the next week: some thoughts on how to close the JavaScript knowledge gap. Stay tuned.