In Tech Stack Modernization, Volume 1, I discussed why I'm evaluating new clientside frameworks, and I listed my goals and requirements.
You'll note that I prefer small focused libraries over kitchen sink frameworks, which is part of the reason I like Knockout.JS so much.
Because of that preference, Angular was a bit of a tough sell for me, but after struggling with framework selection I decided to hold my nose and dive in!
Disclaimer: I'm way far away from being competent in Angular, so while I have opinions, I consider them highly subjective, weakly held and likely based on misconceptions. ☺︎
I spent a bunch of hours just learning Angular. After that, I spent another 10 hours starting to build my application and attempting to cover some of the complex areas.
Before I go further, some history: AngularJS was released in 2010 and gained popularity quickly. It always had some issues and problem areas, so I stayed away from it. Those issues eventually led the team to release a new version that was completely incompatible with the old version.
That brings me to my first issue with Angular: the names are confusing and it's extremely hard to google for resources. The new version was originally to be called Angular 2.0, but they are already on version 4 due to semantic versioning. The website is Angular.io, but I guess people just call it "Angular." When trying to find answers to questions I was constantly finding resources for the old version, though it wasn't always apparent at first glance. The docs for Angular aren't bad, but I was impressed with how difficult it was to find answers to specific questions on the web (by which I mean Stack Overflow).
The second thing to know is that Angular is big—really, really big. It's not really comparable with VueJS, KnockoutJS or React. All of those are view model frameworks that do one thing well and rely on other libraries to provide extra functionality. Angular feels more like a platform than a framework. It has many concepts and a big learning curve, one of the biggest I've seen in a while.
While I was able to make stuff work, I don't feel like I'd be productive in Angular for weeks, and probably not doing normal things the "right" way until I'd been at it for a few months. Given the size and the amount of plumbing/boilerplate code, Angular feels "enterprisey" to me; it's not something I could deploy on a small 20 hour project, nor something I could easily plug into an existing web application.
The Good Parts
Tooling. It's great, and I appreciate that they choose to embrace TypeScript. Visual Studio has lots of support for Angular, automatically grouping your related client side CSS, HTML and TS files together.
Startup. Using a project bootstrap tool (coincidentally written by the author of Knockout) I was able to create a skeleton project in Visual Studio that had WebPack hot module loading as well as server side compilation of Angular templates baked in. (I later broke that feature with some framework code I added, but I'm supposed to be talking about the good parts.)
Structure. Angular is super opinionated (which is either good or bad, depending on your preferences). There's an "Angular way" to do things, including how you structure your project. Once you learn it, it's likely easy to work on different Angular projects and feel at home. If you don't want to have to make decisions about dependency injection, routing, etc., then Angular is helpful because it makes those choices for you.
The Bad Parts
The learning curve. While I was trying to do my demo project, I kept falling into time-sucking rabbit holes where I'd spin my wheels trying to figure out some issues. I felt like I found rabbit holes inside of rabbit holes!
Separate files. Like many frameworks, Angular takes a "component" based approach, with each component having a separate HTML, CSS and TS file. I'm personally trending towards the single file (e.g. JSX) approach for components. I find it helpful to have the CSS and the code that affects the HTML in the same file. Additionally, in Angular the component class has to reference the template and style URLs manually, which just feels like pointless repetition.
Scoped CSS implementation. Both VueJS and Angular provide a mechanism for mutating your component's CSS so that it only applies to that specific component. This is a nice idea, but didn't work well for me in Angular. First, it's automatic instead of something I can opt in to. Second, it doesn't work for targeting nested components; I needed to add ugly "/deep/" overrides to my CSS to prevent scoping modification. You could argue that I shouldn't be targeting child components like this, but sometimes multiple child components need to share some styling elements, and putting them in the parent can be the cleanest/fastest option.
Component coupling. In order to use a component, I need to place an element for it in my HTML template, using an element name that was registered on the component in its class file. Sticking to a strict naming convention can make this work, but it feels like fragile coupling to a magic string to me. Additionally, before I can use a component in my template it must be registered at the application level (or probably better with an ngModule—whatever that is). That feels like too much boiler plate for me.
Component output. Like many platforms, components are implemented as things that look like custom HTML elements in your templates. The components then contain HTML or other content that is rendered. In many other platforms the made-up custom element is removed from the document and is replaced by its content. This makes for nice clean HTML that is easy to style. Angular however outputs the custom components in the DOM tree, which means you have to target them with styles or target around them. If you only use component scoped CSS, this might not bite you, but if you want the ability to do global targeted CSS (or port from existing CSS), this can be a real pain.
On a similar note, Angular was outputting whitespace between repeated inline elements that was breaking my layout (unlike any other platform I prototyped with). There's a Stack Overflow post about the issue and the silly work-arounds needed to overcome it.
Language translation. Angular comes with extensive internationalization support, but the actual text replacement happens at compile time, either just-in-time (which they warn might be slow) or ahead of time. That didn't seem like it would work for our needs, where our users can switch language preferences on the fly, and we wanted our translations to be populated dynamically from a database. I found ways to do the localization dynamically at runtime, but they were more complex than other platforms.
At the end of my prototype I decided that Angular didn't meet my needs. I could have worked around the issues I ran into, but even after all the time I spent with it I felt I was a long way off from knowing the platform.
Due to the complexity and spin up, I'd say Angular would work best in a company that needed a platform for huge applications and wanted to make a long term investment. Don't expect developers new to Angular to be productive quickly, but once you've paid the spin-up costs, the platform brings a lot of functionality out of the box. Much like "Nobody ever got fired for buying IBM," I feel like Angular is a similarly safe choice.
In Tech Stack Modernization, Volume 3, I'll take a similar look at Vue.js. Stay tuned.