TL;DR: Don’t use /MV+C/ frameworks such as Angular and Ember for customer facing websites where the user experience is important.
I no longer like AngularJS (or EmberJS) and haven’t done for almost a year. In that time, I’ve seen AngularJS become so prevalent that about two-thirds of the people I speak to (at user groups and conferences) seem to be using it. On some occaisions, it’s use has become mandated by Architects. The following is an argument against it’s use. However, I’ll also try to point out some positives as well as negatives.
Note I have used Angular on a medium to large website and even blogged about it here, so I can understand why people may be drawn to it. In my case, I put it down to inexperience with frontend development at the time.
The Good Parts
Why would people use Angular?
- It abstracts developers from browser nuances (ala jQuery)
- It abstract boiler plate code such as marshalling data to/from the DOM.
- It allows for web components (e.g. Angular directives) which can be shared across teams or open sourced on the web
- It helps to establish some good practices such as:
- dependency injection
- unit testing
- asynchronous ajax and promises
- It allows a more semantic web setup where the server provides a JSON API which can be reused by other clients – e.g. native android/iOS apps.
- It allows you to build single page apps, which avoids flickering due to a complete page reload.
I think only points 2, 3 and 6 are worth considering – I’ll address these later.
Points 1 and 4 are more about enforcing good practices or wrapping people in cotton wool – good frontend devs don’t need this assistence. In any case, there are lighter weight alternatives.
Point 5 is (very) rarely a worthwhile argument. If your site is that important/hit-up, expose a separate JSON API for people who may want to use your data.
The Awful Part
Unless you also render a page server side which is (a lot) more work and/or duplication.
Everything in the
head section an a
html document is loaded before the
head due to:
- the total page rendering time can be increased due to image loading etc being delayed (e.g. from
imgtags in the
Increasing the page render time by several seconds (or more) is bad for many customer facing websites such as point-of-sale or self-service websites. Conventional wisdom has it that “speed is a feature”. Many companies such as Amazon have done tests which have shown that even speed increases in the order of 100’s of milliseconds has a marked impact on the revenue.
For a more complete discussion on these topics, please visit the following links:
Even with browser side caching, first-time or infrequent users suffer and first impressions are very important. These users probably have no love/affinity for your website or brand. If it loads more slowly than what they expect, they may either give up or possibly use another communication channel instead. If most of your users are in the “infrequent” category, you need to treat page rendering times seriously.
Some people argue that loading Angular separately from a CDN avoids this problem, the premise being that a user will have already visited another site which uses AngularJS and so it will be cached in the browser. This of course relies on the other site to have used the same version of Angular and the same CDN as what you use (which I think is unlikely). It also forces your website to load it separately to your application code – requiring another HTTP request. The net affect of this is that first time users are penalised further.
The Bad Parts
SEO. Sure, there are solutions to this but they involve extra cost and complexity just to get back to where we were before using frameworks such as Angular.
Angular is too large and complicated. If something doesn’t work as expected (or is not documented), you’ll find yourself trawling through a large source file. This wastes substantial amounts of time. In addition, sometimes it’s really hard to work around or extend Angular without modifying it’s source.
Lock-in. Once you’ve “angularified” a site it’s hard to go back.
It’s hard (often impossible) to reuse server-side templates.
Template system. This either leads to a “chatty” application (which loads each template from the server via a separate HTTP request) or a large HTML file which has all the templates stuffed somewhere in it (e.g. in the
head). As Paul Irish has pointed out, the first 14kB are very important. Will the extra templates push your HTML over that threshhold?
Jack of all trades. With Angular, you’re obliged to use several mediocre services such as
$q. It is difficult to substitute these services, and even if you can, you have to load the extra bytes.
Lack of graceful degredation. I’m guessing that most people still have to support Internet Explorers 8/9, even if it accounts for maybe only 10% of users. I find the “easy” way to deal with these browsers is to either polyfill them or else gracefully degrade, whichever is easier. For example, I only show the desktop view on IE 8 (no responsiveness) and I don’t worry about avoiding complete page reloads. Angular forces me to offer the same experience for both IE 8/9 and modern browsers. This can waste a lot of time, especially when using the more advanced features of Angular such as directives with transcludes. It also penalises modern browsers which have to load code only required for older browsers. Polyfills and Prollyfills FTW.
Ajax loading – avoiding the page flicker problem.
Use Twitter style fragment loading and
pushState, with a fallback to a full page re-load for browsers which don’t support
What’s really great about this is that it can be “bolted on” as a progressive enhancement and turned-off just as easily.
I suspect modern browsers already do DOM diffs when updating a page or page fragment. Hence I’m not that excited by React.js in that regard.
Data marshalling to/from the DOM
I haven’t used an alternative to Angular for this, so I’m open to suggestions. There are many lighter weight libraries to try though, e.g. Rivets.
In any case, the websites which most benefit from this are CRM style websites which are not generally customer facing.
Again, I’m open to suggestions for this as well. Rivets purportedly does this as well as many other light-weight libraries.
There is also the new Web Components spec which can be used in modern browsers.
In any case, server side composition is much better than browser side composition from a customer experience perspective as it doesn’t require extra HTTP requests.
I’m struggling to see a use case for Angular or Ember. The only one I can think of is for back-office websites where the customer already has affinity with the brand. If the website is doing a lot of data marshalling or could benefit from off-the-shelf components (which require minimal styling), then these frameworks could be of benefit.
The only thing that would change my mind on some of the above would be Isomorphic Applications. In other words, if we could run Angular on the server-side, that would fix “The Awful Part” above.
The upcoming SDPY protocol would also have a positive impact, allowing templates to be loaded via ajax with less penalty. This by itself would not sway me to use Angular however as it does not fix “The Awful Part”.