Angular 17 Sucks
An objective analysis of Angular 17 and why developing with it sucks.
- Home
- Angular 17 Sucks
Defining a Good Web Development Toolset
Web development has to be one of the most quickly evolving disciplines in programming.
New Javascript frameworks seem to come out so rapidly that it can make a developer's long term
project "obsolete" before they even finish it. Therefore, it is very important to be objective when
choosing a toolset to work with rather than just following the development "fashion industry".
Below I have laid out an analysis that will show you that Angular 17 Sucks and why you should look
elsewhere for you latest web development project. Should you choose WebRocketX or Vue.js for you
next project instead? That depends on the nature of your project so you decide, but for now we will
focus on how Angular 17 holds up to suck analysis.
First of all. Let's talk about a good toolset. A good client side web development toolset should have the following characteristics
Angular 17 Sucks For Developers As The Following Analysis Shows
So, let's see how Angular 17 holds up against these criteria. Angular's performance on each criteria is given a 1 to 10 rating. 10 being the best.
Angular 17 is not intuitive or easy to learn. In fact, a whole cottage industry of Angular training
classes have sprung up because Angular is difficult to wrap your head around and has a big learning curve.
I have developed web applications for 15 years and I am quite fluent with HTML, CSS, javascript, java, jsp,
struts, Spring MVC, JSF, and jquery, and Angular was not easy for me to learn. I can't imagine what it is like
for a web developer newby straight out of college.
For some reason, Angular has to create a completely new ecosystem, complete with Angular specific nomenclature,
abstraction, object hierarchy, and even pulls in Typescript. Yes, you can probably take some classes, do some tutorials,
copy and paste some examples, and start to put together a web application but when your code doesn't work will
you really have any idea why. What is the angular lifecycle exactly? When are your constructors called?
How are you objects scoped? How do they really interact? What events are registered on DOM objects and
how are they triggered. You will spend a lot of time learning that or just do trial and error until your code
eventually works. When you get pretty good at it you will feel like a really intelligent person and maybe
even start drinking the Angular cool aid. Nobody likes to admit they learned something overcomplicated
and esoteric, so most people will eventually convince themselves that this is something good, but it's not.
Angular runs like a big black box and you can forget about what you know about the DOM tree because
you will not being doing any DOM manipulation on your own. Angular really runs more like a big plugin,
rather than a javascript library. Its engine and deployed object might as well be written in machine language
because it's not accessible to the developer anyways. A starting Angular 17 project has 31,000 files in its folder.
That is quite a mass of javascript, so it's clear that your code is no longer really directly interfacing with the browser.
It is really just written to interface with an API, which is the Angular engine. Every line of code you write will
be particular to Angular, and a new developer learning Angular will not really learn how to develop web applications
outside of this specialized bubble.
Writing a web application involves doing several things. Firstly you want to display an interface in the
browser, and secondly you want to render dynamic values into certain parts of that layout. These values
typically come from a database. You will need to allow the user to input new information and send it
to the server, and have some client side validation of that information. Lastly, you want the user to
be able to navigate to different parts of the web application.
Classic web development made a lot of these steps very intuitive and easy to learn. HTML and CSS allowed
the developer to display the interface. JSP's and PHP allowed for intuitive insertion of dynamic content into
this layout on the server, and javascript allowed selective manipulation of the DOM on the client side for
validation, navigation, and any other logic that needed to run client side. These different technologies ran
their code in different layers of the web application lifecycle and allowed for clean separation of their duties.
As always spaghetti code could be created but the architecture itself was very cleanly organized. So, if
we had to break this architecture down into its core components they would be HTML, CSS, javascript, JSP,
Server side controller (worked along with JSP).
Angular unfortunately adds two more logic layers to this technology sandwich, which are underlined. It's
core components are HTML, CSS, typescript (javascript equivalent), templates (client side JSP equivalent),
Json (server side JSP equivalent), Router (client side controller equivalent), and the
client side Angular Object Model.
So, we are going from 5 logical layers to 7 logical layers with Angular, which is a 30% increase in layer complexity.
Keep in mind that these extra 2 layers need to be logically sewn together with everything else
making the complexity even worse.
So, why are we counting the json layer as extra. It's actually quite simple because the developer has to double
render the data. The data is rendered once into json in the service and rendered again into the layout in the template.
However, someone could make the argument that services as a whole are worth the extra effort because they are
reusable and can be consumed by other applications. Furthermore, a web application using jsp's could also consume a
service and therefore make this extra layer a wash. Those would be good points.
However, the real pain point with Angular is its object model. It is truly an extra logical layer in Angular development,
and adds a lot of complexity to an application. In Angular 17, data does not flow from the server into text which is rendered
into the DOM. Instead it flows into a memory object model which is bound to the DOM with Angular registered events.
This extra layer would of course be a horrible idea to maintain by yourself but Angular does this all automagically so the
developer doesn't have to do it right? Not quite. Instead a whole bunch of structure and code and bindings all have to
be made and variable names have to be matched and everything has be set up just perfectly in order for things to be
constantly kept up to date and coordinated. You have to create an object reference for every instance of dynamically
displayed information and also for user input elements located in the page.
The Angular object model is where the real pain begins because your pages start to look like objects within objects instead
of HTML. So you end up creating an Angular memory object tree that is tightly coupled to your DOM object tree. Imagine
this in the physical world. Two dissimilar trees tightly wired together at multiple nodes. It sounds like a tightly bound,
brittle, inflexible mess doesn't it? Well, welcome to Angular.
Another abstraction is that all of your template snippets are abstracted because they live with each one of your objects
that is bound to them. This can facilitate reusability of this layout but more often it just makes it harder to see the whole
web page in one view during development.
If that doesn't suck enough, now put in the other ugly facts.
Angular does provide feedback in the browser script output console (using development tools) when things break.
However, it is often far from being precise. Something as simple as leaving out a library import can result in very
general errors that tell the developer nothing of the actual issue. The relative crappiness of the Angular debug
feedback is something that has to be experienced firsthand to really be appreciated. Using an IDE that supports
Angular and Typescript does help but it still does not compare to a good java IDE which will guarantee you do not make errors.
Keep in mind that the Angular paradigm moves all of your web development code to the browser. This means you will
be writing a very large amount of script compared to other paradigms. Javascript used to be sprinkled on top of the web
development "layer cake" after the page was rendered to the browser. Therefore, it was definitely a much smaller percentage
of your code. Now javascript is delivering everything, the controller, the view, and all the business logic. This is a big
responsibility for a loosely typed language. Javascript has never been known for the quality of its error stack trace. It is
quite common to simply get an "object undefined" error which tells you nothing and this behavior does not change with Angular.
Since all of your html is delivered from javascript you have no opportunity to view the HTML source in the browser as you
would with a traditional web page. Yes, you can use the development tools object inspector to see the rendered DOM
model in the page, but this is after the fact, because if your HTML is not rendering as you think it would you still cannot
see what exactly was delivered to the browser.
Angular can register hundreds of events on your rendered DOM. It does this to implement its bindings and other logic.
The developer has no way to see all these events handles because they are not visible in the DOM or the source.
When something starts breaking in the UI and events are triggering in odd ways the only problem solving tool the
user has is trial and error. This problem is not new and has existed ever since developers started using javascript
to register event handles on DOM nodes instead of coding in a visible onclick or onmouseover event in the tag itself.
However, when you were writing your own javascript event handlers you could at least look through your own script to
find them. Underneath Angular's hood is 31,000 source files and looking through them is not an option.
The Angular Object model, aka component, that has to ride along with the layout adds a layer of complexity that simple
didn't exist in web applications before. Sewing this object model together with the DOM object (template) and then
sewing this model together with service objects that are sewn together with json objects, forces the developer to write a lot
of code. The developer will also need to work their way through this relationship chain anytime a new data element is
added the page as well.
Another source of unnecessary keyboard work is the fact that imports have to be referenced at the top of the file with an
import statement and then referenced again. Typing the same thing multiple times is so much fun. Here is an example
and the following link.
Angular is full of this kind of repetition.
https://angular.io/guide/sharing-ngmodules
Someone developing the Angular framework realized at some point that Angular forced user's to create a lot of files and lot of code.
This is why Angular gives the user CLI commands to create files for new objects such as components and services. Isn't supplying
the developer with code generation tools a big red flag that you are making the developer do a lot of tedious boiler plating that
could simply be avoided by designing the framework better?
I think a rating of 3 is actually being kind to Angular for this criteria. The only reason it's a 3 instead of 2 is because the
framework is generally flexible enough to allow for customization.
The Angular compilation engine must be written in a very rudimentary style because every object has to reference every
object explicitly, plus you have to provide the compiler with full lists of your files. Nothing seems to be done by convention.
Imagine programming a java application and having to maintain another file listing all of your class files and their paths
just so the compiler can find them. Java doesn't work like that. The java compiler finds your files because they are in your project.
Half of the errors I make in Angular are just assuming the compiler knows classes by name. Not the case, adding any
component to Angular requires putting it in lots of places. The CLI to create a component even adds a reference to
the main module for you just in case you would forget. The idea of adding a package and then getting all the objects
in it does not seem to be supported either. Nope, you will have to list them all out in the import statement and in
the ngModule decoration. Have fun. Here is where all the fun begins.
https://angular.io/guide/file-structure
Angular facilitates javascript unit testing, because it is baked into its architecture. I am of the mindset
that your javascript layer should be so trivial that unit testing it is a waste of time, but obviously
with the amount of javascript you will be writing in this framework unit testing is necessary.
An Angular generated DOM is not harder to "Selenium" test than a DOM rendered any other way.
Angular supports putting fixed IDs on tags and fields which is really the most critical thing that any
integration testing test suite needs.
Angular does not support any kind of drag and drop development interface. Furthermore, it's libraries like Angular
Materials do not make for easy "lego" type page layout because every downloadable component requires matching
Typescript classes to be manually coded to be wired to it. Angular's complicated design alone also lends itself to
slow development for all but the most experienced developer.
Furthermore, the embedding of HTML in templates is a substantial barrier to the use of Web Designers (layout specialists)
on an Angular project. Web Designers are not usually the same people that do javascript development and by breaking
their layout into many abstracted snippets of code their job working on an integrated page becomes that much more difficult.
Web designers faced similar issues with JSPs but the sharding of the page and the abstraction in Angular is even more pronounced.
Angular appears to perform well on all major browsers.
Angular applications by design download and cache all of a web applications pages immediately after download.
Therefore, very large web applications with 100s of pages will perform very poorly when a user logs into Angular.
In fact the browser can hang an unacceptable amount of time after login. The newer generation of Angular deals
better with this situation than Angular JS did but its solution called "Lazy Loading" requires a significant amount of
configuration to maintain. As can be seen by looking through their documentation, it's not pretty.
https://angular.io/guide/lazy-loading-ngmodules
Once an Angular app is downloaded on a browser its ability to scale by load is only limited to the ability of the services it calls to scale.
Angular by design downloads and caches all of the pages that a user could possibly need. This means that these pages are
downloaded regardless of the user's authorization level. Therefore administrator type pages and the attack surface for
them are theoretically present when a user with less authorization logs in. To avoid this security risk, developers would
have to make available different versions of the application for different types of users. Since many of the pages would
be shared this will make for a maintenance mess.
Theoretically Angular users could be hitting against multiple service endpoints. However, forcing the user to login every time
they hit an endpoint is unacceptable as is storing their credentials on the browser. Therefore, architectures that allows a
login token to be downloaded to the browser and then used for the remainder of the user's session have been developed
and these architectures are generally complicated because this token has to be recognized by all endpoints. Typically
companies skirt this issue by serving the Angular static content from the same server that will also serve as a proxy for the services.
This way the user only has to authenticate once and will also meet single origin browser security policies when calling the services.
Angular supplies no mechanism for server side errors, a developer will need to come up with this on their own.
The solution will need to inspect every incoming json response for server side errors and have a universal handler for them.
Angular forms template and reactive forms both supply a mechanism for client side single field validation.
Implementing combination multi field validation can be done but is more tricky.
Angular works well with CSS and CSS libraries like bootstrap. However, Angular does not lend itself to
working with standard javascript and jquery running in parallel. The reason being that any direct DOM
manipulation of the UI with javascript will often run afoul of Angular's built in event registration and UI routing.
Since Angular will be automatically manipulating the DOM according to its bindings it can easily pull the rug out
from other DOM event bindings and node additions done by a developers custom javascript, especially elaborate
javascript libraries like jquery UI. Furthermore, navigation in Angular frequently regenerates an entire view from
scratch. Therefore, any independent javascript written directly against the DOM has to be done with knowledge
of the Angular life cycle.
The internationalization of labels on a web pages traditionally was done using a resource bundle on the web server.
Since the resource bundle was stored in RAM even very large key value pairs with phrases registered in the 1000's
would perform well when rendering different localities. Internationalizing with Angular would require treating
labels as another type of json loaded data. Downloading a json resource bundle for a large application will
require pull down 1000s of phrases. Both the download and the binding of the bundle to the labels will perform
poorly with large data sets.
Angular results in the user's experience being intuitive with the exception of the behavior of the back button.
Angular treats the routing to any URL as a forward motion into that URL even if the user used the back button.
Therefore, by default, nothing the user typed into the previous page will be there for them. The developer can
make the data stay by mapping the form fields to a service that persists longer than the page, but other DOM
manipulation will be lost unless specifically coded to regenerate from a service variable. The back button is
a major challenge for the web developer and is important to the user and Angular does little to solve this problem.