As has been previously discussed, JavaScript has the propensity to be very untidy if you let it be. This isn’t a problem unique to JavaScript, of course – many other languages suffer from a lack of native organization, especially for specific tasks.
It is for this reason that frameworks exist – to give us some structure upon which to build, the foundation for our edifice of code. Let’s dig a little deeper into what a JavaScript framework looks like, and why you might want to use one.
What is a JavaScript Framework?
First off: Let’s define, in brief and general terms, a JavaScript framework. Definition varies by the framework, but most follow the pattern familiar to anyone with some experience with server-side frameworks (or Smalltalk-80, for that matter) – that is, some implementation of MV*, ie. MVC (Model-View-Controller), MVP (Model-View-Presenter), etc.
Models in a JS framework, much like their server-side brethren, represent your application’s data (users, photos, blog entries, sales figures, etc.) This data could be drawn from and kept in sync with your server, via a persistence method like ajax or websockets. Or it could exist entirely client-side, either transitory and living in memory, or persisted to client-side mechanisms like localStorage or IndexedDB. Most modern frameworks offer means by which to group models together – that is, to arrange and treat them in a manner analogous to rows within a table.
Views are a bit more amorphous – depending on the framework, they might be as simple as a set of templates, or possess all the logic, routing and data-binding that might be the role of the Controller in another framework. Either way, the view’s role is to maintain the state of a DOM element and it’s child nodes.
Partly because of the flexible definition of what composes a View, MVC often becomes instead MV, where what the value of is depends on the framework – it could be a layer that keeps your views updated with changes to the models and vice versa, it could be here that routing is handled, often times it’s here that views are created, grouped, manipulated, bound to different models or collections of models, and so on. Because the views so often contain significant logic about what is being presented and how it should be interacted with, as a consequence of the DOM Events model, the final element of the MV* pattern fulfills different roles in different frameworks.
Why use a JS framework?
In general terms, for the same reasons you would use a framework on the server-side: adding organization and structure to your code (especially in a manner well suited for collaboration), separation of concerns as per the above mentioned MV* pattern, abstraction of some low-level details, papering over of implementation differences between platforms, and a bevy of useful built-in functionality. In many cases, the point is simply to avoid having to re-invent the wheel for each project.
More specifically, a JS framework is particularly helpful for applications where much of the business logic is going to take place on the client-side – routing, templating, first-pass model validation, table building and pagination – pretty much whatever you might have used the server for in the past, but now without the latency and overhead that additional HTTP calls would have incurred.
It was never good practice to have the server do a bunch of work and spit out a gob of html to insert – this approach is less readable, harder to maintain, and harder to debug then returning just the needed data; and woe to those who include javascript in the chunk of html! Now, there’s absolutely no excuse for it, and many good reasons and a lot of functionality to support doing most of the work client-side. A good REST API returning JSON and a JS framework are a natural pair.
As an example, many JS frameworks include client-side routing, using the history API and/or hash-fragments – making single page apps with identifiable and even uniquely navigable URLs not just possible, but relatively easy (depending on how you go about it). Multi-page applications can also benefit from the routing, of course – there’s very few cases these days where a page is likely to remain static throughout it’s display lifetime, and using routing to pull in views, which automatically populate some sub-section of the page with a template and bind to a model, is a much cleaner solution than, for instance, a mass of jQuery swapping DOM elements in and out and binding in multiple places to different elements and events.
JS Frameworks vs. jQuery (et al.)
On that topic, why use a framework versus jQuery and it’s constellation of plugins, or Prototype, Mootools, and so on?
The simplest answer is: this is the wrong question. In most cases, you wouldn’t use a JS framework instead of jQuery – you might, however, use a JS framework with jQuery. A framework is not a compatibility layer like jQuery – as an example, the framework itself might work in IE8, but it isn’t going to give you a polyfill for old IE’s non-standard attachEvent method.
If your project needs to support client-side routing, JS templates, models and collections, data persistence with the server, clean interaction with a REST API, etcetera, you probably want to use a JS framework.
If you need to support old versions of browsers that may not share an API or support the most recent advances for things like the Selectors API, event listeners, Promises and XMLHTTPRequest, then you probably want to use jQuery.
If you need both, you probably want to use both. They are (potentially) complementary.
Why NOT use a framework?
JS frameworks are not a panacea – they have use-cases for which they are the best solution, and then there are cases where they are unnecessary cruft, slowing down page-load times and obstructing progress.
When considering whether you should use a JS framework, you should consider the following:
-
Do I already know a JS framework? Here, the consideration is learning curve. Obviously, learning new things is part of the job (and one of the best parts, at that), but if there’s a massive time-crunch to get the project out the door, there may not be the luxury of time needed for learning how to employ a framework to it’s best effect. Better to stick to what you know and do it well, then to implement a framework poorly.
-
Is my project big enough? Here, the consideration is the amount of code you expect to need to write for the project – for the same reasons you might eschew a big library like jQuery for a small project, you might want to eschew a framework as well; and if you’re expecting only a few source files with a couple hundred lines of code, you can probably do without the organization a framework offers. Of course, none of us are prescient and projects have a tendency to increase in scope, so think hard about this one – it’s harder to fit a framework in after the fact than to start with one.
-
Is my project complex enough? Here, the consideration is the complexity of the client-side logic – if all of the work is going to be done server-side and the pages are going to be largely static, a framework isn’t going to add much value.
-
Is page-size at a premium? Here, the consideration is the extra kilobytes a gzipped framework library is going to cost to transfer – for the most part, this isn’t going to be a concern, especially for single page apps, but if one of the other considerations is borderline and page-size matters, you might decide to do without the framework.
-
Am I familiar with JavaScript? Here, the consideration is how well you know the language and available APIs. This isn’t a project-specific consideration, but rather a developer-specific one. If you already know JavaScript inside and out, you’ll be able to wring the most out of a framework; if not, you’ll need to be careful not to let the framework become a crutch. Reading through the source of some popular frameworks is a great way to become more familiar with the language and some laudable practices.