Angular is an Onion

Victor Savkin
Nx Devtools
Published in
5 min readAug 7, 2020

--

Angular is an onion with the following layers:

  1. The core capabilities of the framework (e.g., renderer, compiler)
  2. Core APIs (e.g., ng-if, ng-for, decorators, animations)
  3. APIs for building applications (e.g., router, forms, state management)
  4. Basic CLI capabilities
  5. CLI Plugins (karma, protractor, webpack, tslint)

Layer 1 is the most technically challenging, but, at the same time, you only need one good implementation of this stuff, and it will work reasonably well for most applications. This layer is also really well-defined. You can even benchmark your implementation to see how good it is. Someone who understands browser internals and compilers is the best person to work on this.

Layer 2 is somewhat similar. The API is narrow, which means that one well-written ng-if is good enough for everyone, and getting feedback from just a couple of teams is sufficient to design it well.

Layer 3 is where things change. Routers, forms, and state management libraries have much broader APIs. As a result, there will always be multiple incompatible implementations (e.g., Apollo and NgRx). Technically, this layer isn’t as challenging as Layers 1 and 2, but it’s harder here to get the API and the dev experience right. You need a lot of feedback. Feedback from developers working at different organizations, building different apps. The more the better.

On Feedback

While on the Angular team, I found working on Layers 1 and 2 straightforward. I knew what needed to be done, and I could rely on the feedback from other teams at Google. If something didn’t work, they would let me know. If something was slow, I’d hear about it.

Layer 3 is a different story. Many, but of course not all, Google engineers have little or no experience outside of Google. They are also very intelligent. The problem with intelligent people with little experience is that they can make anything work, no matter how convoluted that thing is. This is bad feedback because it’s hard to gauge how well the API solves real problems.

It was even tougher for the Angular CLI team. Given that it is not used at Google, it’s almost surprising how great it ended up being. And, in my opinion, it’s due to a very strong eng team consisting of Googlers (in particular Hans Larsen) and external contributors. But there are no miracles. Once you start using the CLI on large projects, you see right away that some use cases don’t work well (e.g., large projects cannot update from one version of Angular to another in a single go. Using peer dependencies for deciding what needs to be updated doesn’t work well, etc..)

What about GitHub issues? GitHub issues are useful for bug reports, but not for assessing dev experience. To know how something feels, you actually need to use it, and use it a lot.

Same story for CLI plugins. As a plugin author, you cannot assess, say, testing tools unless you are using them on real projects with a lot of different teams at different companies.

This situation isn’t unique to Angular or Google. In all large companies I know infrastructure/tooling teams don’t spend much time building applications. And for Layers 1 and 2 this is actually the best arrangement. Let me explain why.

Angular is Many Things

Angular is many things, and some of them are easier for the team at Google to get right. The team is very good at Layers 1 and 2 because the team gets sufficient feedback, and the team has a lot of expertise in this stuff. No one else can do it but them.

To get APIs for building applications (Layer 3) right you actually need to spend most of your time building applications. There is no other way. This isn’t a question of staffing or getting the best people etc. Unless you are in the trenches, you won’t get enough feedback, you won’t feel the dev experience.

That’s why Apollo and NgRx are so robust. They are built by people in the trenches. And that’s why you should look at the angular-routing library by Brandon Roberts, who is a fellow Nrwlian btw.

This cannot be solved by writing more design docs or soliciting more feedback. The Angular community will always be better at this because the community consists of people building applications.

Finally, the CLI and its plugins. Karma, Protractor, TSLint are widely used inside and outside of Google. They have to be supported. No questions about it. The decision to keep them in the CLI is probably the right decision. At the same time, TSLint is deprecated. Karma and Protractor feel antiquated. But I don’t think it’s fair for us to expect the Angular team to provide CLI plugins for all popular testing and linting tools. No other framework team does it.

Pluralism

The Angular team is very good at building frameworks (Layers 1 and 2). We, the Angular community, are good at building applications. So when it comes to APIs for building applications or CLI plugins, we are actually better positioned to get things right. We have the right expertise, and we should use it.

When we need to change the compiler, we have no choice but to wait for the team at Google to do it. But when it comes to changing, say, the forms, we could just do it ourselves. It’s OK to have a different take on forms. And if at one point, some ideas from the new implementation make their way into the Angular repo, that’s even better.

Pluralism is good.

Remember, everything in the Angular repo has to basically work for everyone, and the changes have to made in the backwards-compatible way. These are the tough constraints the Angular team works within. (For instance, the Forms API is a bit clunky because it had to work with and without Observables, and be familiar for AngularJS users.)

A community project doesn’t have to work for everyone, it doesn’t to be backwards compatible. It’s a much better place for experimentation.

Different Take on CLI

We at Nrwl have been doing this for three years — we have our own take on the CLI. If you want to use modern testing and linting tools, run: npx create-nx-workspace --preset=angular to get an Angular CLI-powered Nx workspace with:

  • Jest instead of Karma
  • Cypress instead of Protractor
  • ESLint instead of TSLint
  • “Fixed” ng update
  • Built-in support for NgRx
  • And many other cool things

It’s still Angular, just with a different, perhaps more modern set of tools around it.

Call to Action

In the Angular community we expect the Angular team to provide us with pretty much everything we need to build applications. This is too much of an ask. This isn’t even a question of the team’s resources or skill (the Angular team is very capable) — I don’t think this is desirable. Successful software ecosystems rely on the community to do most of the heavy lifting.

The Angular team is giving us stable and expressive primitives. We can use those to build amazing things like Nx, Scully, NgRx, etc… Let’s fill in the gaps we see, let’s innovate, and by doing so we will help the Angular community and the Angular team.

--

--

Nrwlio co-founder, Xoogler, Xangular. Work on dev tools for TS/JS. @NxDevTools and Nx Cloud architect. Calligraphy and philosophy enthusiast. Stoic.