Skip to content

Thoughts on JavaScript frameworks.

September 8, 2014

Like it or not, JavaScript is the language that we have to use for front end development on the web. And that was fine when all we did was adding some dynamism to the site, perhaps a menu or a date picker. But now the whole web application is often using JavaScript, and whole bits of the page is replaced via Ajax, and everything is clickable and updates automatically, etc. And at that point just having everything in one big JavaScript file is not feasible. And splitting it up randomly into separate files hardly helps as you tend to end up with loads of globals anyway.

To write a full front end JavaScript app you need some sort of structure. The first step there was JavaScript libraries, where jQuery the last few years have pretty much taken over everything. Lately the new trend is frameworks. This can intuitively make sense, as the web is moving from adding a bit of JavaScript here and there, to writing the applications purely in JavaScript. And just as with libraries, there are infinite amounts of them, and it will probably take a few years until we can shake out some winners. Because with frameworks it’s likely to be more than one winner, as the requirements for frameworks are quite different for different people and different use cases.

My requirements on a JavaScript framework may be somewhat different than others, but this list is based on my experience so far, which admittedly has been neither extensive, not good. But these are things I’ve found lacking.

Library-ishness

The first part of a good JS framework is that it is usable as a library, or that at least a lot of parts of the framework can be used in a simple way without using all of the framework. This is required for many reasons. Firstly this helps you get started with the framework as you can easily use parts of it without drowning.

Today many web applications are written in back-end frameworks, like Ruby on Rails or Django, and then applying a JavaScript framework whose main usage is to write a web application, you end up having two competing frameworks that fight each other. Therefore a framework that is designed only to be used to write full applications in JavaScript is going to be a bad fit for a web application written in Django. This requirement is quite unique for JavaScript Application frameworks, as you are unlikely to start using a bit of Ruby-on-Rails in a J2EE app, for example.

This means that if the framework is not a good fit for slowly taking over existing applications, you end up not using it in existing applications, and then  you need to learn some other library or framework in that situation. That means you need to know at least two frameworks for doing the same thing, which is a waste of brain power. One framework should be enough.

Modularity

To be able to handle big applications you need to be able to make things modular, and you need a way to handle module dependencies. This is something JavaScript traditionally has been very bad at, and there are several efforts to do something about that. A framework needs to support this, and you need to be able to declare your dependencies. You should also preferably have some sort of name space handling so that not all modules that are required for your application is available everywhere, as that clutters the name space. Think about Python’s import statement here, for an example of what you want.

Something you also want is an ability to declare your dependencies after the application has loaded. This is so that you can create a pluggable application. This is again mainly a requirement for applications that run on a traditional server-side framework. These frameworks often have their own system for making things extensible and pluggable. So you might want to write a plugin for your server-side framework that uses a date input with a nice date selector, and then you need that plugin to be able to say to the JavaScript application that is needs a specific module. Ways of doing that that are not good enough includes having to edit a separate file that lists all your JavaScript dependencies, because that file may not be under your control, as it’s a part of the web application, and not a part of the plugin you are developing.

Legacy form handling

Related to this is that you want to be able to integrate the JavaScript frameworks form handling with the back-end applications form handling. Some JavaScript frameworks assume that you are submitting any form with JavaScript collecting the values from a form, and then making a POST in that JavaScript. But if your widgets assume this, they may not work in a normal form submit, because they may not have a real <input> tag to submit the value. That also makes it harder to use just bits of the framework. Either that, or the framework needs to take over any <form> tag that uses a framework widget by magic. But magic is usually a bad idea.

HTML is declarative, your JavaScript App should also be.

Lately a new attitude has shown up in JavaScript, and that’s using a more declarative style. Instead of having an initializing script that tags specific <input> tags as using a date-time widget, you set some sort of declaration on the tag, and the widget happens automatically. Although this is just a small step from having just a special class for this, and using jQuery to set all inputs with that class to use the widget, it’s a change in attitude. And it’s an important change, because if you in a JavaScript framework need to write a lot of JavaScript manipulation of the HTML you have broken much of the purpose and principle of HTML. HTML is declarative, and you should be able to think about it in that way, and not have to think about it as something that in the future needs to be modified.

So with declarative JS, instead of creating HTML and then writing code that manipulates this HTML you write some sort of self-contained modules that are applied automatically. Of course, in the end it’s still JavaScript that manipulates the DOM, but it’s now done in localized and contained ways. And if you think this is obvious, then you are probably writing your declarative JavaScript in that way already, so pat yourself on the back!

The less JavaScript the better

Quite often, both for libraries and frameworks, you end up writing a lot of JavaScript. This sounds reasonable, but it should not be. Not only because writing and developing JavaScript sucks, but also because the JavaScript and HTML lives in a very tight integration, and the HTML is often designed by somebody who often do not know JavaScript. So less JavaScript is necessary not only to save us poor Python programmers from the pain, but also to make it possible for designers and usability people to create designs and mockups.

This also ties into the declarative development above. In the ideal world a HTML developer should be able to add a bunch of JavaScripts to his HTML, and then just write HTML code to get most of the web application UI working. (S)he should be able to declare a list of tabs, and have it behave like a list of tabs, and the date-time widget should be declared only with HTML, and the framework should do the magic.

Example: Patterns

Patterns” is a library of JavaScript widgets and functionality that works entirely from a declarative style. It aims and to a large part succeeds to make it possible for HTML hackers to design a webapp. This is because the concept in fact comes from a designer, Cornelis Kolbach. With Patterns you for example make a HTML injection like this:

<a href="demos/frobber.html#content" class="pat-inject">Demo the frobber</a>
<section id="content">
  HTML to be replaced.
</section>

The “pat-inject” class means the <a> link will load the href, find the tag with the ID “content” and inject it in the current page at the content-id. All of the usage of Patterns is similarly free of Javascript, while the patterns themselves is of course written in JavaScript.

Using Patterns is very simple, and you can freely pick and choose what you use, because it is in fact not a framework at all, it’s a library. It’s also badly documented and setting up an environment where you can develop patterns was at least a few months ago exceedingly complicated. But it serves well as an example of what you can achieve with declarative JavaScript libraries.

Example: AngularJS

AngularJS is a framework, and it’s very frameworky. It also claims to apply a declarative attitude, and indeed, the “Hello World” example of AngularJS requires you only to create the main application module. But then it quickly breaks down.

If you want to have a pre-filled value in the input when you load the page, commonly done when you are editing something, then the examples tell you to do this with very imperative JavaScript. This seems very strange, especially considering that most inputs have a value attribute, but that’s just ignored. AngularJS also breaks pretty most of the requirements I have for a good framework, and I admit it, this whole post was prompted by me trying to use AngularJS. Trying to use a tags-widget written with AngularJS in a form led to a lot of pain, partly because AngularJS does assume you will submit the form with AngularJS, as explained above.

AndularJS is trying to be modular, and you can indeed write new declarative modules, by adding directives. But using them independently can be quite tricky, and the first problem is that you define AngularJS dependencies in the same line of code that you create the application. That’s equivalent to having to declare all your imports in the first lines of your Python application! There is no way to add a dependency once the main application has been created.

That means that you actually have to make your own system for declaring dependencies where your plugins can add their dependencies to a list to be used when initializing the main AngularJS module.That adds a layer of complexity and brittleness to your web application. In Horizon, the admin UI for Openstack, there are now at least two different ways of declaring your plugins AngularJS requiements, perhaps more. This adds “technical debt” and complexity for no good reason.

AngularJS is definitely not a framework where you can use bits and pieces, you have to drink the cool-aid. And this seems to be the general consensus; AngularJS is good for writing apps from scratch, but not for adding functionality to existing applications.

Conclusion

The conclusion is that writing frameworks is hard, and for JavaScript possibly even harder. I have over the weekend gotten several recommendations for other JavaScript frameworks and for me none of them seem to fit the bill. I look forward to being proven wrong.

Correction and further thoughts

I had been pointed to Polymer, but I saw it as a widget library, not a framework, and after reading more documentation, I still do. It looks similar to Patterns, but with better documentation, and widget animations. I hope to get a chance to use it. It may very well be that the perfect framework is a combination of Polymer as a widget library and one or several bits that provides only frameworky bits for when writing pure JS frontends.

You need some sort of module encapsulation, and you need to be able to declare dependencies and add dependencies in a modular way. Either adding them at any point in the app initialization, or you need multi-step initialization, so you first create the app, then add dependencies, then initialize it.

I suspect that you also might need some sort of model/view/template mechanism. Obviel could fit the bill there.

From → django, javascript

Leave a Comment

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: