An Angular Upgrade Service?

Earlier this month, I polled people on LinkedIn to know which version of Angular they’re currently using at work. Here are the results:

First, I was pleasantly surprised that most of them (58%) are fully up-to-date or just one major version behind. What’s more worrying is that 24% of them use a non-supported version. So I asked why people use older versions of the framework (you can contribute here with your comments if you want), and of course, I knew more or less what the answers would be: Time – Budget – Dependencies.

This made me think about the following: What if there was an Angular Upgrade Service? A hands-on service you could subscribe to that would keep your projects up-to-date. Do you think that would be of interest?

I’m always looking for gaps to fill in the front-end development space. This is why I created the Angular certification program, the React certification program, and just helped launch a Javascript certification program!)

In any case, if you think you could use an Angular Upgrade Service, please let me know (respond to that email or reach out on LinkedIn – always happy to connect!), and I might beta-test that idea with you in the next quarter.

How to use Jest for Angular Unit Tests?

Karma is deprecated, and the Angular team is working on official support for Jest and Web Test Runner. Today, I want to highlight how to set up your Angular project for Jest since it’s prevalent in the Javascript ecosystem (React, etc.). It’s super fast and 100% browserless, making running tests on a continuous integration server easy.

Also, the syntax is essentially the same as Jasmine/Karma, so you won’t have to change your tests much unless you do extensive mocking in Jasmine.

Here are the steps I’ve used on over 28 repositories so far, with great success:

  1. Uninstall Jasmine, Karma, and all associated types
    npm uninstall karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter @types/jasmine jasmine-core

  2. Install Jest, its types, and presets for Angular
    npm i --save-dev jest @types/jest jest-preset-angular

  3. Create a setup-jest.ts file in your project’s root folder
    And add that single line of code in it:
    import 'jest-preset-angular/setup-jest';

  4. Create a jest.config.ts file in your project’s root folder with the following command
    npx jest — init

    Then ensure you have the following config options set in that file:
    preset: 'jest-preset-angular',
    setupFilesAfterEnv: ['./setup-jest.ts']


  5. Update your tsconfig.spec.json file

    Your compilerOptions should look like this:
    "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "types": [ "jest" ],
    "esModuleInterop": true,
    "emitDecoratorMetadata": true
    },


  6. Last step: Update package.json
    In the scripts section, replace the test entry with:
    "test": "jest",

And… that’s it! You can now launch npm run test to run your tests with Jest. Sure, a schematic would be better, but those steps take only 2-3 minutes to implement for now.

How to migrate Angular syntax to the latest features?

I posted about how to update your version of Angular a while back. Still, with the ongoing updates in the framework, such as standalone components, the new control flow syntax, and the inject() function, there are quite a few new options that aren’t required but can still be adopted widely.

For instance, if you want to remove your ngModules and go full-standalone; there’s a migration command for that:

This command will ask you about different options, such as removing unnecessary ngModules, and switching your AppComponent to standalone bootstrapping.

If you want to get rid of NgFor, NgIf, and the like, you can migrate automatically to the new control flow syntax with:

Another migration command was added in Angular 18.2. This one is to migrate your dependency injection syntax to use inject() instead of constructors:

Finally, and also added in Angular 18.2, is the migration to use lazy-loading on all routes:

This last command can be applied to a subset of routes by using the path argument:

The official documentation for all these migrations can be found here.

Debugging without breakpoints

I covered the Angular Devtools extension in a newsletter entry last year, and this browser extension keeps getting better and better.

For instance, with Angular 17, an injector tree view feature was added.

With the addition of signals to the framework, we get even better insights and access to our data in a static way that doesn’t require any breakpoint. For instance, if you want to see what’s the current value of a signal in one of your components, the extension shows that value:

We can tell right away that title is a Signal and that the current value is “Welcome to our store”. With Observables, we don’t have that luxury:

So that’s one more good reason to use signals in our Angular applications and perhaps one more reason to try the official Angular dev tools extension if you haven’t done so yet.

Another cool feature is that when you select a component in the tree view, you can see the text "== $ng0" showing up next to the component name:

This $ng0 is a variable that can be explored in the browser’s console. If I type $ng0 there, here’s what I get:

I can explore that component and any service injected into it right from the browser’s console—no breakpoint is needed.

Bonus tip: If you selected another component previously, it is now known as $ng1. The one before that, $ng2, and so on.

Angular Component Testing with Cypress

Great news! Thanks to all your contributions, I’m happy to organize another coffee-fueled 2-hour workshop in January, which will be about testing Angular components with Cypress!

The date is January 18th, 2024, at 9 am US/Pacific (time zone converter here).

Like last time, the workshop will be on Zoom, and we’ll have a few hands-on exercises. A recording will be shared with all attendees after the workshop. You can register here and contribute here to keep me caffeinated.

If you have ideas for future workshops, please let me know. I do have a few, but I’m always open to suggestions.

Make types from JSON samples

First, a quick announcement: I’m running a donation-based online Angular Signals Workshop on December 14th and January 18th. If you’re interested, feel free to show your interest here, and remember that you don’t have to pay anything if you don’t want to or can’t.

Earlier this year, I shared how to generate type definitions for Typescript using json2ts, but that website has disappeared. A suggested superior alternative is Quicktype, which can also create DTOs and has several config options.

Recently, I heard about another option called MakeTypes. It’s as simple as the two previous tools, and it can also be downloaded via npm to be part of your local development process if that’s what you want:

Again, all you need to do is copy-paste your sample JSON and get instant Typescript interfaces (or proxy classes) to use in your project. And if you don’t want to use a website to create your types, head to the NPM page to download the tool.

How to update your Angular CLI?

We touched on many Angular 17 updates so far, and if you want to test those out on a fresh new project, you’ll need to upgrade your Angular CLI to v17.

Here is the most straightforward command to upgrade your global Angular CLI to the latest version:

npm install -g @angular/cli@latest

That’s it! The -g flag indicates we want to install that CLI globally, and the @latest at the end ensures we’re getting the latest stable version.

Angular 17: New devtools injector tree view

Another Angular 17 update is the release of a new DevTools panel called Injector Tree. It’s a good option to visualize both your element hierarchy and injector hierarchy, and it is accessible as a third tab in the Angular DevTools browser extension available for Chrome, Firefox, and Edge:

When we click on that tab, a tree view of all hierarchies shows up on the screen:

For a clearer view, we can check the option “hide framework injectors” to focus on our code:

Clicking on an injector (such as root) shows the list of all injectables/services available in that injector:

This new tab seems to be just getting started, and more information will be added later. Even though the Devtools is a browser extension, the Injector tree tab only works for apps using Angular v17+. I tried an Angular v16 app with no success.

Angular 17: New esbuild builder with Vite

Who doesn’t like faster builds? Since Angular 2, the Angular team has consistently worked on making our builds quicker and faster. Angular 16 included a developer preview of a new build system based on esbuild and Vite.

With Angular 17, this feature is now enabled by default for new apps, with reported speed improvements of over 67% in most applications.

To enable this new build system in existing apps (that use v16+), open your angular.json file and look for all the places where @angular-devkit/build-angular:browser is used:

Then, replace those instances with @angular-devkit/build-angular:browser-esbuild

And your next run of ng serve or ng build will automatically use this new build system. Nice and easy! If you use server-side rendering or have tweaked the builders in the past, you’ll want to look at the extra instructions listed on this page.

RxJs eslint plugin for Angular

Last month, I discussed eslint and how to use that tool to parse your code and receive feedback on best practices and possible improvements.

Today, I want to mention an eslint plugin explicitly written for RxJs with Angular: eslint-plugin-rxjs-angular.

This plugin adds three possible validation rules:

All rules are optional, and it doesn’t make sense to use all of them at once because these best practices are contradictory in the sense that the goal is for you to choose one of these three approaches and be 100% consistent with it:

  1. The first rule will enforce that you always use the async pipe in your components.
  2. The second rule doesn’t care about the async pipe but wants to ensure you unsubscribe on destroy.
  3. The third rule is the most specific, as it enforces that you always use a Subject with takeUntil to unsubscribe in your components.

I’d suggest using the first rule only because we covered before that the async pipe is the safest and most performant option. And remember that you can always use the async pipe. There are no excuses!