What's new in Angular CLI 7.1?

Angular CLI 7.1.0 is out!

If you want to upgrade to 7.1.0 without pain (or to any other version, by the way), I have created a Github project to help: angular-cli-diff. Choose the version you’re currently using (6.2.1 for example), and the target version (7.1.0 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/6.2.1…7.1.0. It can be a great help along the official ng update @angular/core @angular/cli command. You have no excuse for staying behind anymore!

Let’s see what we’ve got!

Package manager auto detection

The CLI should now do a better job to detect the package manager you use (NPM or Yarn), and use it for the various commands like ng update or ng add.

tslib as a dependency

The CLI applications have a new required dependency: tslib. This Microsoft library contains TypeScript helpers. The CLI now uses one of them to avoid repeating code for every class regarding imports. The use of these helpers is activated by an option importHelpers in the tsconfig.json file:

"experimentalDecorators": true,
"importHelpers": true,

By including these helpers, and avoiding to repeat the same code over and over, the sizes of your bundles should be slightly reduced (don’t expect miracles though).

@angular/http removed

@angular/http has been deprecated for a long time in favor of @angular/common/http, and it is now removed from the generated package.json file.

That’s all for this very small release, I hope you enjoyed reading this blog post. Stay tuned!

All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!


What's new in Angular 7.1?

Angular 7.1.0 is here!

Angular logo

Not a lot of new features in this release: the Angular team is still mainly focused on the Ivy project, rewriting the Angular compiler and runtime code to make it smaller, better, faster.

Beginning of Bazel support

A new @angular/bazel package appeared in the Angular repository, containing the stepping stones for building our Angular applications with Bazel. It also contains a schematics collection (with a target currently called bazel-workspace) to generate the necessary files in an Angular CLI application.

npm i -g @angular/bazel
npm generate @angular/bazel:bazel-workspace my-app // adds the Bazel build files to a CLI project

I guess that in a near future, we should be able to directly generate a CLI app with Bazel build (something like ng new my-app --collection=@angular/bazel).

The bazel-workspace target already allows to build, serve, test and launch the e2e tests with Protractor. This is still quite experimental.

Note that Bazel is now published on NPM directly, removing the need to install it manually.

Router

CanActivate guard can return a UrlTree

The signature of CanActivate changed and it now can return Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree instead of Observable<boolean>|Promise<boolean>|boolean. It means that whereas previously you would have returned a boolean (or something that yields a boolean later), you can now return the URL where you want to redirect your user.

So you can write:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
  return this.userService.isLoggedIn() || this.router.parseUrl('/login');
}

instead of:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
  const loggedIn = this.userService.isLoggedIn();
  if (!loggedIn) {
    this.router.navigateByUrl('/');
  }
  return loggedIn;
}

The difference is also that now the router will behave correctly if several guards trigger different redirects (it was not the case before, and that could lead to non deterministic behavior in redirections). Note that you can also use router.createUrlTree() to build a UrlTree with parameters.

New option for runGuardAndResolvers

runGuardsAndResolvers is one of the configuration options for a route, allowing to define when the guards and the resovlers will be run for this route. By default, they run only when the path or matrix parameters change (value paramsChange). You can override this behavior by using another value for this option like paramsOrQueryParamsChange, to also trigger the guards and resolvers if a query parameter changes, or always to trigger them if anything changes.

Angular 7.1 introduces a new possible value: pathParamsChange. Using this value, the guards and resolvers will run if a path parameter changes, but not if a query or matrix parameter changes.

Forms

updateOn in FormBuilder

The updateOn option is available since Angular 5, but it was only usable if you used the constructor of FormGroup directly:

this.userForm = new FormGroup({
  username: '',
  password: ''
}, {
  validators: Validators.required,
  updateOn: 'blur'
});

It is now possible to use it via the group helper method of the FormBuilder. Note that this updated group method can now take an AbstractControlOptions as the second parameter, allowing to have a more coherent API, and use exactly the same syntax as in FormGroup:

this.userForm = fb.group({
  username: '',
  password: ''
}, {
  validators: Validators.required,
  updateOn: 'blur'
});

The old form of options is now deprecated (it was using validator and asyncValidator instead of validators and asyncValidators).

Service Worker

It’s now possible to be notified when a user clicks on a push notification, via the notificationClicks observable on the service SwPush.

Ivy update

The Ivy rewrite is still in progress, but I noted that I missed a nice addition: there will be public discovery utils that can be used to debug your application in the browser. Several functions will be available in the browser console: getComponent(target), getDirectives(target), getHostComponent(target), getInjector(target), getRootComponents(target), and getPlayers(target).

In Chrome for example, you can inspect an element and that will store the current element in a variable called $0. Then in the browser console, you can do ng.getComponent($0) and it will return the component associated to the element! You can check out Jason Aden talk at AngularConnect for more info on the topic.

All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!


What's new in Angular CLI 7.0?

Angular CLI 7.0.0 is out (in fact we even have a 7.0.1 available)!

If you want to upgrade to 7.0.1 without pain (or to any other version, by the way), I have created a Github project to help: angular-cli-diff. Choose the version you’re currently using (6.2.1 for example), and the target version (7.0.1 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/6.2.1…7.0.1. It can be a great help along the official ng update @angular/core @angular/cli command. You have no excuse for staying behind anymore!

Let’s see what we’ve got!

Interactive prompts

One of the major additions to this version: the CLI now offers interactive prompts on several commands to let the developer choose some options or names.

For example, if you run ng new with CLI 7.0, then it asks you:

? What name would you like to use for the project?
? Would you like to add Angular routing? y/N
? Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS
  SCSS   [ http://sass-lang.com   ]
  SASS   [ http://sass-lang.com   ]
  LESS   [ http://lesscss.org     ]
  Stylus [ http://stylus-lang.com ]

You can enter the name of the project, choose to add or not the routing support (with No as a default value if you just press Enter), and pick which CSS pre-processor you want, allowing to choose between CSS, SCSS, SASS, LESS and Stylus by using the arrow keys.

Note that all these options were already available, but you had to know the correct flags to add. For example ng new ponyracer --routing --style=scss.

If you don’t specify one of the options, a prompt will appear. You can of course deactivate this interactive mode, by using ng new ponyracer --no-interactive (no prompt at all), or ng new ponyracer --defaults (uses the default option of the prompt if it exists).

All the ng generate commands (component, service, pipe, etc.) will also ask for the name of the entity to generate if not provided.

You can add these prompts to your own schematics too. See how easy it is to add, for example in ng new.

Fun with flags!

A lot of flags have been added to various commands!

ng serve

A --verbose flag is now available for ng serve and ng build, displaying how much time each task took, how much each asset weighs, etc.

ng build

ng build now has a --profile flag.

It outputs two files:

  • chrome-profiler-events.json
  • speed-measure-plugin.json

The first one is a Chrome profile file, that you can load via the Performances tab in your Chrome Dev Tools. The second one is the result of the Speed Measure Webpack plugin and contains information about how much time each plugin took.

This is not really intended for us, but to help the CLI team improving some projects with long build times. If you are in this case, you can now offer proper information to the team about your build, and they might be able to speed things up in future releases.

The CLI README now also has a dedicated section to CPU profiling of your build.

ng generate

ng generate component now accepts --viewEncapsulation=ShadowDom to reflect the new view encapsulation option added in Angular 6.1.

ng new

We already talked about --no-interactive and --defaults, but ng new also earned a flag called --no-create-application. If you use it, the CLI will create a workspace with the NPM, TypeScript, TSLint and Angular CLI configurations, but with no application (so no src and e2e directories).

Along the same lines, a new flag called --minimal will generate a workspace with a project, but with the bare minimum: no unit tests or e2e tests, no TSLint either, and it uses inline styles and templates in components. This can be useful if you just want to setup a repository for a quick proof of concept.

ng test

The --reporters flag for the test command is back, after disappearing for a few versions. It allows to directly specify which reporters you want Karma to use, so it can be useful on a CI for example.

ng xi18n

You can now turn off the progress of the build when extracting the i18n messages with: ng xi18n --no-progress.

TypeScript 3.1 support

As Angular 7.0 now requires TypeScript 3.1 (check out our article about Angular 7), the CLI officially supports it too. This also includes a few optimizations in build-optimizer specific to Angular 7.0/TS 3.1.

Terser instead of UglifyJS

As uglify-es is no longer maintained and uglify-js does not support ES6+, the CLI team has moved to Terser for the minification phase of the build. Terser is a fork of uglify-es that retains API and CLI compatibility with uglify-es and uglify-js@3. It shouldn’t really change the results, but it fixes a few long standing issues with UglifyJS, like production builds that weren’t working in old Firefox ESR versions.

Configuration

In angular.json, you can now ignore certain files in your assets, with the brand new ignore option:

"assets": [
  {
    "glob": "**/*",
    "input": "src/assets/",
    "ignore": ["**/*.svg"],
    "output": "/assets/"
  },
],

On the polyfill side, the reflect-metadata polyfill (core-js/es7/reflect) is now only included in JiT mode, as it is not needed in AoT (production) mode. If you run ng update to update to 7.0, it should be automatically removed and your bundle will be a few kB lighter!

Talking about bundle sizes, a new application now has some “budgets” set by default:

budgets: [{
  type: 'initial',
  maximumWarning: '2mb',
  maximumError: '5mb',
}],

When you build your application, you’ll see a warning if the bundle is over 2MB, and an error if it is over 5MB. You can customize these limits of course (see our article about the CLI 1.7, the version that introduced budgets).

Performances

The CLI team released a new package (still experimental), called benchmark. The goal is to help benchmarking a NodeJS process, by measuring the time, CPU usage, memory usage, etc. So it’s not specific to the CLI itself. You can check out the README to learn more. The CLI team probably intends to track the performances of the various tools they are currently releasing, but maybe you can use it on your projects too.

.npmrc per project

You can now define one .npmrc file per project in your workspace, making it easier to deploy artefacts to your Nexus or Artifactory repository.

Breaking change

This is a small one, but worth noting: the CLI no longer inlines the assets less than 10kb in the CSS. If you had a small image, it used to be inlined directly in the generated CSS.

Eject is not coming back

As you may know, the CLI used to have an eject command, making it possible to customize the Webpack config directly (at the price of losing the CLI support). It was temporarily removed in CLI 6.0 due to the internal refactoring, but it will not come back. It will be removed completely in 8.0. The team thinks that the new configuration format provides enough flexibility to modify the configuration of your workspace without ejecting. They also mention ngx-build-plus if you want even more customization without ejecting.

That’s all for this release, I hope you enjoyed reading this blog post. Stay tuned!

All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!


What's new in Angular 7?

Angular 7.0.0 is here!

Angular logo

Not a lot of new features in this release: the Angular team is mainly focused on the Ivy project, rewriting the Angular compiler and runtime code to make it smaller, better, faster. But Ivy is not ready for prime time yet.

So don’t expect a lot of shiny things in Angular 7.0: there was not enough material to make a video as we did for Angular 5 or Angular 6. This will be a short blog post for once, and a fast and easy upgrade for you!

TypeScript 3.1 support

One of the main new features is the support of TypeScript 3.1, which is the latest release! It is in fact mandatory to bump to TS 3.1 for Angular 7. Usually Angular lags a few releases behind, so it’s great to be able to use the latest TypeScript version for once! You can check out what was introduced in TypeScript 3.0 and TypeScript 3.1 on the Microsoft blog.

Angular compilation options

As you may know, you can define compilerOptions for TypeScript and angularCompilerOptions for Angular in your tsconfig.json files:

{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    "experimentalDecorators": true,
    // ...
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true,
    "preserveWhitespaces": true,
    // ...
  }
}

TypeScript allows you to extend the compilerOptions of another file (see the extends part in the example), but it was not doing anything with the Angular compiler options. The Angular compiler is now fixed, and you can define Angular compiler options in a base config, then extend them in another file. The options will be merged with the one defined in the inheriting config file, as they are for the TypeScript compiler options!

Ivy progress

The rewrite is making progress, but Ivy is still not usable in this release. If you refer to the official feature tracking, a good chunk of the work is done. But in reality, there is still a long way to go before we can use it.

Ivy has several pieces:

  • ngtsc: the compiler that compiles your Angular application and generates JavaScript from your HTML templates. This piece of code has made good progress but still misses a few features.
  • ngcc: a tool that explores all the dependencies you have, to convert existing code into “Ivy compatible” code. This is still very early stage, and barely usable at the moment if you don’t know how to workaround a few issues (Olivier and Pete from the Angular team were nice enough to help me).
  • the renderer itself, which takes the generated code and makes the magic happen at runtime. It still moves a lot, as new optimizations and new issues are found by the team.

Another part that is eagerly awaited is the support of “runtime i18n”. The implementation work has just started this week, so this is also far from being done.

I gave Ivy a few shots lately but it is definitely not ready for prime time yet. Internally at Google, the Angular team needs to migrate the huge number of projects they have to gather feedback and fix issues. So it will take a few more months.

But you can check it out yourself, as the CLI added an --experimental-ivy flag to generate an application with the configuration needed to try it.

ng new ivy-test --experimental-ivy
cd ivy-test
$(npm bin)/ngcc
ng serve --aot

Note that the change detection is not working as I’m writing these lines, so this is very limited right now :).

Slots with Angular Elements

It is possible to use ViewEncapsulation.ShadowDom since Angular 6.1, which is great for Angular Elements (Angular components packaged as Web components that you can use alone). But there was a missing feature to be able to use <slot>, a new standard HTML element, introduced by the Web Component specification. This feature is now available, enabling components with a template like:

@Component({
  selector: 'ns-card',
  template: `
    <header>
      <slot name="card-header"></slot>
    </header>
    <slot></slot>`,
  encapsulation: ViewEncapsulation.ShadowDom,
  styles: []
})
export class CardComponent {
}

That can later be used as an Angular Element like this:

<ns-card>
  <span slot="card-header">Become a ninja with Angular</span>
  <p>A wonderful book from Ninja Squad</p>
</ns-card>

Router

A new warning has been added if you try to trigger a navigation outside of the Angular zone, As it doesn’t work if you do so, Angular now logs a warning (only in development mode). This is pretty rare but can happen for example if you try to redirect your users when an error occurs in the application by providing a custom ErrorHandler (as the handleError method will run outside the ngZone to avoid a potential infinite loop). The warning looks like:

Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?

Sadly, this introduces warnings in your unit tests if you use the router in some of them, and looks like it’s an issue in Angular itself (see this issue if you want to add a thumb up).

Another internal work that we can’t really see has been the rewrite of the router to use a single Observable under the hood, that will automatically cancel the previous navigations. It will not affect you, but should fix a bunch of issues when multiple navigations were triggered at the same time and will allow new features more easily in the future.

Deprecations

As it’s usually the case with major releases, a few things have been deprecated. If you are using <ngForm> to declare a form in your template (you don’t have to, as form also activates the NgForm directive), this selector is now deprecated and should be replaced by <ng-form>.

As you can see, the release contains very few interesting features, but Ivy is making progress and Angular 8.0 will probably have more cool stuff!

In the meantime, the upgrade of your applications should be very easy.

All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!


Angular Performances Part 5 - Pure pipes, attribute decorator and other tips

This is the last part of this series (check the first part, the second one, the third one and the fourth one if you missed them), and this blog post is about how you can improve the runtime performances of your Angular application with pure pipes, the attribute decorator and other tips. If you are the lucky owner of our ebook, you can already check the other parts if you download the last ebook release.

Now that we have talked about first load, reload, profiling and change detection strategies we can continue our exploration of the tips for better runtime performances.

Pure pipes

As you know, you can build your own pipes to format and display your data. For example, to display the full name of a user, you can either write a method in your component:

@Component({
  selector: 'ns-menu',
  template: `
      <p>{{ userName() }}</p>
      <p>...</p>
      <p>{{ userName() }}</p>
  `
})
export class MenuComponent {

  user: UserModel = {
    id: 1001,
    firstName: 'Jane',
    lastName: 'Doe',
    title: 'Miss',
  };

  userName() {
    return `${this.user.title}. ${this.user.firstName} ${this.user.lastName}`;
  }
}

or write a custom pipe to encapsulate this logic:

@Component({
  selector: 'ns-menu',
  template: `
      <p>{{ user | displayName }}</p>
      <p>...</p>
      <p>{{ user | displayName }}</p>
  `
})
export class MenuComponent {

  user: UserModel = {
    id: 1001,
    firstName: 'Jane',
    lastName: 'Doe',
    title: 'Miss',
  };
}

with DisplayNamePipe looking like:

@Pipe({
  name: 'displayName'
})
export class DisplayNamePipe implements PipeTransform {

  transform(user: UserModel): string {
    return `${user.title} ${user.firstName} ${user.lastName}`;
  }

}

This takes a little bit more work, but writing a pipe allows to reuse it in other components.

What you may not know is that using a pipe is also more performant. By default, a pipe is “pure”. In computer science, we call “pure” a function that has no side effect, and whose result only depends on its entries. A pure pipe is pretty much the same: the result of its transform method only depends on arguments. Knowing that, Angular applies a nice optimization: the tranform method is only called if the reference of the value it transforms changes or if one of the other arguments changes (yes, a bit like the OnPush strategy for components).

It means that whereas a method of a component is called on every change detection, a pure pipe will only be executed when needed, and only once in a template if it is used with the same input value and arguments (as in my example).

By default, a custom pipe is pure, so that’s great! But sometimes it’s not a right fit.

In my example, if we mutate the user to set its firstName to a different value, the pipe never refreshes… It’s pretty much the same issue that we had with the OnPush strategy: the reference of the value doesn’t change, so the pipe does not run again.

Here you have two solutions:

  • carefully use the pipe with immutable objects (do not mutate the user, create a new user with the new firstName);
  • mark the pipe as “impure”, and Angular will run it every time. You lose a tiny bit in performance, but you are sure that the displayed value is refreshed.

To mark a pipe as impure, just add pure: false in its decorator:

@Pipe({
  name: 'displayName',
  pure: false
})
export class DisplayNameImpurePipe implements PipeTransform {

  transform(user: UserModel): string {
    return `${user.title} ${user.firstName} ${user.lastName}`;
  }

}

To sum up:

  • a pure pipe is not called as often as a method in a component
  • but it doesn’t run again if the input value is mutated, so use carefully.

Split your template wisely

Based on what we learned, here is a trick that doesn’t use a specific Angular API, but can be easily understood.

Let’s say you have a component displaying a huge list of results, and an input allowing to update this list. As you don’t want to update the list on every key pressed, you are debouncing what the user types, and then update the list. Something like:

@Component({
  selector: 'ns-results',
  template: `
    <input [formControl]="search">
    <h1>{{ resultsTitle() }}</h1>
    <div *ngFor="let result of results">{{ result }}</div>
  `
})
export class ResultsComponent implements OnInit {

  search = new FormControl('');
  results: Array<string> = [];

  constructor(private searchService: SearchService) {
  }

  ngOnInit() {
    this.search.valueChanges
      .pipe(
        debounceTime(500),
        switchMap(query => this.searchService.updateResults(query))
      )
      .subscribe(results => this.results = results);
  }

  resultsTitle() {
    return `${this.results.length} results`;
  }
}

You may think that the change detection is not very often called, as you update the list only when the user has stopped typing. But in fact the change detection is called on every event in the template (so here on every key pressed). You can check it out by adding a simple console.log in resultTitle, and see it called in the developer console on every key pressed.

To avoid detecting change on the list elements even if not needed (as the results will not change on every new value, but only after some time), the idea is to split your view into two parts, and to introduce a sub-component to display the results. This component can be switched to OnPush and the change detection will only update it when really needed, and not on every key press.

@Component({
  selector: 'ns-results',
  template: `
    <input [formControl]="search">
    <ns-results-list [results]="results"></ns-results-list>
  `
})
export class ResultsComponent implements OnInit {

  search = new FormControl('');
  results: Array<string> = [];

  constructor(private searchService: SearchService) {
  }

  ngOnInit() {
    this.search.valueChanges
      .pipe(
        debounceTime(500),
        switchMap(query => this.searchService.updateResults(query))
      )
      .subscribe(results => this.results = results);
  }
}

With the sub-component looking like:

@Component({
  selector: 'ns-results-list',
  template: `
    <h1>{{ resultsTitle() }}</h1>
    <div *ngFor="let result of results">{{ result }}</div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ResultsListComponent {

  @Input() results: Array<string> = [];

  resultsTitle() {
    return `${this.results.length} results`;
  }
}

This is a simple pattern to use, often referred to as the smart/dumb component pattern: a smart component deals with data loading, event handling, etc., and simply passes the data to display as input to a second, dumb component. The only responsibility of the dumb component is to display the data, and to emit events to its parent smart component using outputs. This dumb component is the one with the large template, containing many expressions. But since its state only changes when its smart parent passes a new input, it can use OnPush and thus saves a lot of expression evaluations.

Attribute decorator

When using an @Input() in a component, Angular assumes that the value passed as input can change, and does what it takes to detect the change and pass the new value to the component. Sometimes, it’s not really necessary, as you may want to only pass a value once to initialize the component and never change it. In this very specific case, you can use the @Attribute() decorator instead of the @Input() one.

Let’s consider a button component, to which you want to pass a type to set its aspect (something like primary, success, warning, danger…).

Using an input, it would look like:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'ns-button',
  template: `
    <button type="button" class="btn btn-{{ btnType }}">
      <ng-content></ng-content>
    </button>`
})
export class ButtonComponent {

  @Input() btnType;
}

that you can use with:

<ns-button btnType="primary">Hello!</ns-button>
<ns-button btnType="success">Success</ns-button>

Since the input is a simple string that never changes, you can switch to use an attribute:

import { Attribute, Component } from '@angular/core';

@Component({
  selector: 'ns-button',
  template: `
    <button type="button" class="btn btn-{{ btnType }}">
      <ng-content></ng-content>
    </button>`
})
export class ButtonComponent {

  constructor(@Attribute('btnType') public btnType: string) {}
}

This produces a “bind-once” like effect, avoiding Angular to do unnecessary work. But keep in mind this only works with non-dynamic, string inputs.

Conclusion

This series of blog posts hopefully taught you some techniques which can help solve performance problems. But remember the golden rules of performance optimization:

  • don’t
  • don’t… yet
  • profile before optimizing.

As a famous computer scientist said:

Premature optimization is the root of all evil. - Donald Knuth

So strive to make the code as simple and correct and readable as possible, and only start thinking about profiling, then optimizing, if you have a proven performance problem.

If you enjoyed this blog post, you may want to dig deeper with our ebook, and/or with a complete exercise that we added in our online training. The exercise takes an application and walks you through what we would do to optimize it, measuring the benefits of each steps, showing you how to avoid the common traps, how to test the optimized application, etc. Check it out if you want to learn more!


Angular Performances Part 4 - Change detection strategies

This is the fourth part of this series (check the first part, the second one and the third one if you missed them), and this blog post is about how you can improve the runtime performances of your Angular application with change detection strategies. If you are the lucky owner of our ebook, you can already check the other parts if you download the last ebook release.

Now that we have talked about first load, reload and profiling we can continue our exploration of the tips for better runtime performances.

Change detection strategies

When we explained how Angular detects the changes in your application, we showed the tree of components and said that Angular starts by checking the root component, then its children, then its grand-children, until all components are checked. Then all the necessary DOM updates are applied in one batch.

But you may be wondering if it is a very good idea to check every component on every change. And you’re right, that’s often not really necessary.

Angular offers another change detection strategy: it’s called OnPush and it can be defined on any component.

With this strategy, the template of the component will only be checked in 2 cases:

  • one of the inputs of the component changed (to be more accurate, when the reference of one of the inputs changes);
  • an event handler of the component was triggered.

This can be very convenient when the template of a component only depends on its inputs, and can give a serious boost to your application if you display a lot of components on screen! But once again, be very cautious before applying this optimization: if the preconditions end up not being respected, you will lose your hairs wondering why the component (or any of its descendants) isn’t always repainting itself after a change.

Let’s take a small example to demonstrate.

Imagine that we have 3 components. A very simple ImageComponent:

@Component({
  selector: 'ns-img',
  template: `
      <p>{{ check() }}</p>
      <img [src]="src">
  `
})
export class ImageComponent {
  @Input() src: string;

  check() {
      console.log('image component view checked');
  }
}

used in a PonyComponent:

@Component({
  selector: 'ns-pony',
  template: `
    <p>{{ check() }}</p>
    <ns-img [src]="getPonyImageUrl()"></ns-img>
  `
})
export class PonyComponent {
  @Input() ponyModel: PonyModel;

  check() {
    console.log('pony component view checked');
  }

  getPonyImageUrl() {
    return `images/pony-${this.ponyModel.color}-running.gif`;
  }
}

used itself in a RaceComponent:

@Component({
  selector: 'ns-race',
  template: `
    <h2>Race</h2>
    <p>{{ check() }}</p>
    <div *ngFor="let pony of ponies">
      <ns-pony [ponyModel]="pony"></ns-pony>
    </div>
    <button (click)="changeColor()">Change color</button>
  `
})
export class RaceComponent {

  ponies: Array<PonyModel> = [{ id: 1, color: 'green' }, { id: 2, color: 'orange' }];
  colors: Array<string> = ['green', 'orange', 'blue'];

  check() {
    console.log('race component view checked');
  }

  changeColor() {
    this.ponies[0].color = this.randomColor();
  }

}

The RaceComponent displays two ponies, and the user can change the color of the first one by clicking on the Change color button.

With the current default change detection strategy, every time that we have a change in the application, all 3 components are checked.

We added a check() method in each component, called in each template: it allows us to track if the component is checked or not. And indeed in our example, we can see in our console:

pony component view checked
image component view checked
pony component view checked
image component view checked
race component view checked

(we can see that twice actually, because we are in development mode, see the section about enableProdMode above).

OnPush

But in this case, it’s a waste of time: we know that if the pony doesn’t change, the template of the PonyComponent doesn’t need to be checked. Same thing for the ImageComponent: if the src input is the same, there is no need to recompute the image URL. So let’s switch these components to OnPush, by adding a changeDetection attribute in their @Component decorator:

@Component({
  selector: 'ns-img',
  template: `
    <p>{{ check() }}</p>
    <img [src]="src">
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ImageComponent {
  @Input() src: string;

  check() {
    console.log('image component view checked');
  }
}

Same thing in PonyComponent:

@Component({
  selector: 'ns-pony',
  template: `
    <p>{{ check() }}</p>
    <ns-img [src]="getPonyImageUrl()"></ns-img>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PonyComponent {
  @Input() ponyModel: PonyModel;

  check() {
    console.log('pony component view checked');
  }

  getPonyImageUrl() {
    return `images/pony-${this.ponyModel.color}-running.gif`;
  }
}

When we click to change the color, we will only see in the console:

race component view checked

Which is awesome, because it means that we don’t check the components that we don’t need to check \o/.

OnPush and the mutability trap

But… there is a slight problem: the pony’s color doesn’t change any more!

I picked this example on purpose: even if OnPush is really powerful, it can be tricky and optimizing existing components is not only about adding a few OnPush here and there.

Why doesn’t it work in our case?

Take a closer look to our RaceComponent, and its changeColor method:

changeColor() {
  this.ponies[0].color = this.randomColor();
}

This method mutates the pony in the ponies collection, and this pony is the input of our PonyComponent. Now that we shifted our component to be OnPush, Angular will only run the change detection if the reference of the pony input changes. And when you mutate an object, it’s still the same object, so the reference doesn’t change, and Angular thinks there is no need to run the change detection…

So, is this change detection strategy completely useless? Not really, but it does require you to be more careful.

The simple way to fix our issue is to not mutate our pony in changeColor, but to create a new object:

changeColor() {
  const pony = this.ponies[0];
  // create a new pony with the old attributes and the new color
  this.ponies[0] = { ...pony, color: this.randomColor() };
}

Once you’ve done that, the application is faster and correct. If the user clicks on the button, the changeColor method creates a new pony object with the old attributes and the new color. As this is a new object, Angular will run the change detection in the PonyComponent (an input changed), and then the src input of the ImageComponent will also change, and the image will display the correct color. And, of course, if another event triggers the change detection in RaceComponent, the children component will not be checked (if their inputs did not change).

As you can see, you can quickly fall into a trap when migrating a component to an OnPush strategy, so be careful (unit tests are your friend).

One way to avoid this would be to use a library that enforces immutability. Immutable.js (by Facebook) is such a library. I’ve never used it professionally, so I can’t say if it’s a good fit in an Angular application or not, but you do see it mentioned often on the internets.

There is a last topic we need to talk about: observables.

OnPush, Observables and the async pipe

Let’s say we now have only one component, our well-known PonyComponent. It subscribes to an observable from a ColorService that returns a new color every second. We obviously expect the image displayed to change every second. The developer of this component thought that an OnPush change detection strategy couldn’t hurt. What do you think?

@Component({
  selector: 'ns-pony',
  template: `
      <p>New color every 1s</p>
      <img [src]="'pony-' + color + '.gif'">
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PonyComponent implements OnInit, OnDestroy {
  color = 'green';
  subscription: Subscription;

  constructor(private colorService: ColorService) {
  }

  ngOnInit() {
    this.subscription = this.colorService.get()
      .subscribe(color => this.color = color);
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

Sadly, this doesn’t work. With the OnPush strategy, Angular only refreshes the template if one of the inputs changed (here, there is no input), or if an event was triggered (there is none either). So the color field is updated every second, but the template is never refreshed…

This can be fixed by using the pipe called async.

The async pipe can be used to subscribe to a Promise or an Observable. Let’s use it in our PonyComponent:

@Component({
  selector: 'ns-observable-on-push-with-async',
  template: `<img *ngIf="color | async as c"
                  [src]="'pony-' + c + '.gif'">`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PonyComponent {
  color: Observable<string>;

  constructor(colorService: ColorService) {
    this.color = colorService.get();
  }
}

Now our component is working! The async pipe will trigger the change detection when a new value is received. And you can see that we store the result of async to use it with as. It also frees us to subscribe to the observable in the component, and to remember to unsubscribe when the component is destroyed: async does it for us.

Note that async can lead to several HTTP requests if used several times in a template, and that you can use the “smart/dumb” component pattern to make it easier to use OnPush.

ChangeDetectorRef

There are a few last tricks regarding change detection that I want to show you. They are for more advanced use cases but, you never know, it can be handy one day.

Let’s take an hypothetical use case: you have an observable that emits data very very frequently. In my example, it’s a clock that emits every 10 milliseconds:

@Component({
  selector: 'ns-clock',
  template: `
      <h2>Clock</h2>
      <p>{{ getTime() }}</p>
      <button (click)="start()">Start</button>
  `
})
export class ClockComponent implements OnDestroy {

  time = 0;
  timeSubscription: Subscription;

  start() {
    this.timeSubscription = interval(10).pipe(
      take(1001), // 0, 1, ..., 1000
      map(time => time * 10)
    ).subscribe(time => this.time = time);
  }

  getTime() {
    return this.time;
  }

  ngOnDestroy() {
    this.timeSubscription.unsubscribe();
  }

}

The component uses the Default change detection strategy, so every time the observable emits a new value, the change detection is triggered, the template is refreshed and the clock value displayed is updated.

But, do we really need a hundred updates per second? Our eyes can’t see that fast, and it’s putting pressure on our browser for nothing. And remember that not only this component will be checked a hundred times per second, but the whole application too!

Maybe in that case it would be enough to refresh the time displayed every second for example. To do so, you can completely opt out from the automatic change detection in your component, and handle things yourself, by injecting in your component a ChangeDetectorRef. This class offers a few methods:

  • detach()
  • detectChanges()
  • markForCheck()
  • reattach()

The first two work together: you can indicate to Angular to not care about the component with detach and then manually call detectChanges when you want the change detection to run:

@Component({
  selector: 'ns-clock',
  template: `
    <h2>Clock</h2>
    <p>{{ getTime() }}</p>
    <button (click)="start()">Start</button>
  `
})
export class ClockComponent implements OnDestroy {
  time: number;
  timeSubscription: Subscription;

  constructor(private ref: ChangeDetectorRef) {
    this.ref.detach();
  }

  start() {
    this.timeSubscription = interval(10).pipe(
      take(1001), // 0, 1, ..., 1000
      map(time => time * 10)
    ).subscribe(time => {
      this.time = time;
      // manually trigger the change detection every second
      if (this.time % 1000 === 0) {
        this.ref.detectChanges();
      }
    });
  }

  getTime() {
    return this.time;
  }

  ngOnDestroy() {
    this.timeSubscription.unsubscribe();
  }

}

As you can see, we slightly changed the component to inject ChangeDetectorRef, detach the component from the change detection, and then manually run detectChanges() to trigger it when we need it (every second in our case). The time field is still updated a hundred times per second, but now the clock displayed to our users is only updated every second!

Note that this only triggers a change detection on that component (and its children) every time we run detectChanges().

But there is a way to go one step further, and completely handle it manually, by updating the DOM yourself (and not triggering a complete change detection):

@Component({
  selector: 'ns-clock',
  template: `
      <h2>Clock</h2>
      <p #clock></p>
      <button (click)="start()">Start</button>
  `
})
export class ClockComponent implements OnDestroy {
  time: number;
  timeSubscription: Subscription;
  @ViewChild('clock') clock: ElementRef<HTMLParagraphElement>;

  constructor(private ref: ChangeDetectorRef) {
    this.ref.detach();
  }

  start() {
    this.timeSubscription = interval(10).pipe(
      take(1001), // 0, 1, ..., 1000
      map(time => time * 10)
    ).subscribe(time => {
      this.time = time;
      if (this.time % 1000 === 0) {
        this.clock.nativeElement.textContent = `${time}`;
      }
    });
  }

  ngOnDestroy() {
    this.timeSubscription.unsubscribe();
  }

}

Here we grab a reference to the element we need to update, and then we update the DOM manually when needed, without triggering a change detection.

Another way to do this is possible: you can completely run the code outside of Zone.js, the library that triggers the change detection. To do so, you can inject NgZone, and then use its runOutsideAngular method to execute code outside of its scope:

constructor(private zone: NgZone) {
}

start() {
  this.zone.runOutsideAngular(() => {
    this.timeSubscription = interval(10).pipe(
      take(1001), // 0, 1, ..., 1000
      map(time => time * 10),
    ).subscribe(time => {
      this.time = time;
      if (this.time % 1000 === 0) {
        this.clock.nativeElement.textContent = `${time}`;
      }
    });
  });
}

This produces the same results, but here the rest of the component would still be checked automatically by Angular. runOutsideAngular is more suited to use cases where you want only specific portions of code to run out of the watch of Zone.js/Angular.

As I was saying, this example is a bit advanced, but ChangeDetectorRef can be handy for some use cases. Imagine that the example changing the color of a pony every second doesn’t use an observable, but a simple setInterval.

@Component({
  selector: 'ns-pony',
  template: `<img [src]="getPonyImageUrl()">`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PonyComponent implements OnInit, OnDestroy {

  @Input() ponyModel: PonyModel;
  private intervalId: number;

  ngOnInit() {
    this.intervalId = window.setInterval(() => {
      this.ponyModel.color = this.randomColor();
    }, 1000);
  }

  ngOnDestroy(): void {
    window.clearInterval(this.intervalId);
  }

No visual update… And in that case, we can’t use the async pipe as we did with an observable…

But we can use the markForCheck method of ChangeDetectorRef to manually trigger the change detection in an OnPush component:

@Component({
  selector: 'ns-pony',
  template: `<img [src]="getPonyImageUrl()">`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PonyComponent implements OnInit, OnDestroy {

  @Input() ponyModel: PonyModel;
  private intervalId: number;

  constructor(private ref: ChangeDetectorRef) {
  }

  ngOnInit() {
    this.intervalId = window.setInterval(() => {
      this.ponyModel.color = this.randomColor();
      this.ref.markForCheck();
    }, 1000);
  }

  ngOnDestroy(): void {
    window.clearInterval(this.intervalId);
  }

And it works again!

If you enjoyed this blog post, you may want to dig deeper with our ebook, and/or with a complete exercise that we added in our online training. The exercise takes an application and walks you through what we would do to optimize it, measuring the benefits of each steps, showing you how to avoid the common traps, how to test the optimized application, etc. Check it out if you want to learn more!

See you soon for part 5!


Angular Performances Part 3 - Profiling and runtime performances

This is the third part of this series (check the first part and the second one if you missed them), and this blog post is about how you can profile the runtime performances of your Angular application and how you can improve these runtime performances. If you are the lucky owner of our ebook, you can already check the other parts if you download the last ebook release.

Now that we have talked about first load and reload, we can start talking about runtime performances. But if you run into a performance issue, before trying any of the following tips, you should start by measuring and profiling the application.

Browsers nowadays offer nice developer tools, especially Chrome, which allows to record your application, and analyze its behavior with quite some details. You can even simulate some conditions, like using a slower processor, or using a 3G network. You can also dive into the call hierarchy, and see how much time each function call is consuming.

Profiling

But Angular also offers a precious tool: ng.profiler. It’s not very well-known, but it can be handy as it allows to measure how long a change detection run in the current page took.

You can then try to apply one of the tips we’ll see, and measure again to see if there is any improvement.

In your main.ts file, replace the application bootstrapping code with the following:

platformBrowserDynamic().bootstrapModule(AppModule)
  .then(moduleRef => {
    const applicationRef = moduleRef.injector.get(ApplicationRef);
    const componentRef = applicationRef.components[0];
    // allows to run `ng.profiler.timeChangeDetection();`
    enableDebugTools(componentRef);
  })
  .catch(err => console.log(err));

Then go to the page you want to profile, open your browser console, and execute the following instruction:

> ng.profiler.timeChangeDetection()
ran 489 change detection cycles
1.02 ms per check

You can see how many change detection cycles it ran (it should be at least 5 cycles or during at least 500ms), and the time per cycle. This is a super useful metric, as many of the tricks we are going to show you directly act on the change detection system. You’ll be able to try them, run the profiler again, and compare the results.

You can also record the CPU profile during these checks to analyze them with ng.profiler.timeChangeDetection({ record: true }).

The Angular team recommends to have a time per check below 3ms, to leave enough time for the application logic, the UI updates and browser’s rendering pipeline to fit within the 16 milliseconds frame (assuming a 60 FPS target frame rate).

Let’s discover these tips!

Runtime performances

Angular’s magic relies on its change detection mechanism: the framework automatically detects changes in the state of the application and updates the DOM accordingly. So, as a general rule of thumbs, you’ll want to help Angular and limit the change detection triggering and the amount of DOM to update/create/delete.

To be honest, most applications will be fine, even under heavy load. But some of us will have to recode Excel in the browser for their enterprise, or will have a component with a tree displaying 10,000 customers, or another unreasonable thing to do in a browser. These things are tricky, whatever framework you use. They tend to update a lot of DOM, and have to check a lot of components. A few of the following tricks can help. And a few of these tricks are really mandatory, like the first one.

enableProdMode

When you are in development mode (by default), Angular will run the change detection twice every time there is a change. This is a security to make sure you are not doing strange things, like updating data without following the one-way data flow. If you break the rules, Angular will warn you about it in development, by throwing an exception that will force you to fix your code. But if you are not careful, you will deploy the application in this mode, and change detection will still run twice, slowing your application.

To go in production mode, you need to call a function provided by Angular called enableProdMode. This method will disable the double check, and also make the generated DOM “lighter” (less attributes on the elements, attributes that are added to debug the application).

As usual the CLI got you covered, and the call to enableProdMode is already present in the generated application, wrapped in an environment check: if you build with the production environment, your app will be in production mode.

trackBy in ngFor

This is a simple tip that can really speed things up on *ngFor: add a trackBy. To understand why, let me explain how modern JS frameworks (at least all major ones) handle collections. When you have a collection of 3 ponies and want to display them in a list, you’ll write something like:

<ul>
  <li *ngFor="let pony of ponies">{{ pony.name }}</li>
</ul>

When you add a new pony, Angular will add a DOM node in the proper position. If you update the name of one of the ponies, Angular will change just the text content of the right li.

How does it do that? By keeping track of which DOM node references which object reference. Angular will have an internal representation looking like:

node li 1 -> pony #e435 // { id: 3, color: blue }
node li 2 -> pony #8fa4 // { id: 4, color: red }

It works great, and if you change an object for another one, Angular will destroy the node and build another one.

node li 1 (recreated) -> pony #c1ea // { id: 1, color: green }
node li 2 -> pony #8fa4 // { id: 4, color: red }

If the whole collection is updated with new objects, the complete DOM list will be destroyed and recreated. Which is fine, except when you just refresh a list with almost the same content: in that case, Angular destroys the complete node list and recreates it, even if there is no need to. For example, when you fetch the same results from the server, you will have the same content, but different references as your collection will have been recreated.

The solution for this use-case is to help Angular track the objects, not by their references, but by something that you know will identify the object, typically an ID.

For this, we use trackBy, which expects a method:

<ul>
  <li *ngFor="let pony of ponies trackBy: ponyById">{{ pony.name }}</li>
</ul>

with the method defined in the component:

ponyById(index: number, pony: PonyModel) {
  return pony.id;
}

As you can see, this method receives the current index and the current entity, allowing you to be creative (or simply track by index, but that’s not recommended).

With this trackBy, Angular will only recreate a DOM node if the id of the pony changes. On a very big list which doesn’t change much, it can save a ton of DOM deletions/creations. Anyway, it’s quite cheap to implement and doesn’t have cons, so don’t hesitate to use it. It’s also a requirement if you want to use animations. If a DOM element’s style is supposed to be animated (by transitioning smoothly from the previous value to the new one), and the list of ponies is replaced by a new one when refreshed, then trackBy is a must: without it, the animation will never happen, because the style of the element never changes. Instead, it’s the element itself which is being replaced by Angular.

We have more tips for you, but you’ll have to wait until next week to read about them!

If you enjoyed this blog post, you may want to dig deeper with our ebook, and/or with a complete exercise that we added in our online training. The exercise takes an application and walks you through what we would do to optimize it, measuring the benefits of each steps, showing you how to avoid the common traps, how to test the optimized application, etc. Check it out if you want to learn more!

See you soon for part 4!


The Gradle Kotlin DSL is now documented

More than 2 years ago, I wrote

Kotlin has also been announced as the future language of choice for Gradle, and I can’t wait to be able to use it for my Gradle builds.

It turns out I had to wait quite a bit. Using the Gradle Kotlin DSL is possible for some time now, but it was a bit of a frustrating experience due to the lack of documentation, to the point that I wrote a migration guide a few months ago.

As promised by the Gradle team, a much better, more complete, official migration guide now exists.

The huge, fantastic Gradle user guide, however, still only shows Groovy samples. But not for long. I’ve spent some time, along with other folks, translating all the samples of the user guide from Groovy to Kotlin. The result is already available in the Gradle nightly.

So you have no excuse anymore. Try the Kotlin DSL. It works, it is quite close to the Groovy DSL, but with less black magic involved, and it does allow auto-completion and navigation to the sources in IntelliJ.

Translating the samples has been a great experience. And it helped finding and fixing a few issues, too. Contributing to an open-source project you like and respect is always gratifying. You get the feeling that what you’re doing matters. Gradle folks have been nothing but kind, understanding, helpful, grateful… and demanding.

I didn’t just decide to contribute though. That’s always intimidating: where to start? How to get help? Will I help, or will I be a burden for the maintainers?

I contributed because the Gradle team asked me to. First after I wrote my migration guide, and after when they opened this epic issue, asking for help from contributors, and providing detailed instructions and examples on how to accomplish the task.

I wish more big open-source projects do that. Tagging issues with “ideal-for-contribution” is also nice. What might seem like grunt work for project maintainers or experienced contributors is an interesting challenge and learning experience for casual, less-experienced developers who are willing to help.

So, if you’re an open-source project maintainer and you read this, please make it easy to start contributing on your project. Ask for help. And communicate on public channels (blogs, tweets, etc.) about it. I’m apparently not the only one to have this opinion, so here is some more food for thoughts.


Angular Performances Part 2 - Reload

This is the second part of this series (check the first post if you missed it), and this blog post is about how you can speed up the reloading of an Angular application. In future posts, we’ll talk about how to profile your running application, and how to improve runtime performances. If you are the lucky owner of our ebook, you can already check the other parts if you download the last ebook release.

So, let’s assume a user visits your application for the first time. How to make sure that, when he/she comes back later, the application starts even faster?

Caching

You should always cache the assets of your application (images, styles, JS bundles…). This is done by configuring your server and leveraging the Cache-Control and ETag headers. All the servers of the market allow to do so, or you can use a CDN for this purpose too. If you do so, the next time your users open the application, the browser won’t have to send a request to fetch them because it will have them already!

But a cache is always tricky: you need to have a way to tell the browser “hey, I deployed a new version in production, please fetch the new assets!”.

The easiest way to do this is to have a different name for the asset you updated. That means instead of deploying an asset named main.js, you deploy main.xxxx.js where xxxx is a unique identifier. This technique is called cache busting. And, again, the CLI is there for you: in production mode, it will name all your assets with a unique hash, derived from the content of the file. It also automatically updates the sources of the scripts in index.html to reflect the unique names, the sources of the images, the sources of the stylesheets, etc.

If you use the CLI, you can safely deploy a new version and cache everything, except the index.html (as this will contain the links to the fresh assets deployed)!

Service Worker

If you want to go a step further, you can use service workers.

Service Workers are an API that most modern browsers support, and to simplify they act like a proxy in the browser. You can register a service worker in your application and every GET requests will then go through it, allowing you to decide if you really want to fetch the requested resource, or if you want to serve it from cache. You can then cache everything, even your index.html, which garanties the fastest startup time (no request to the server).

You may be wondering how a new version can be deployed if everything is cached, but you’re covered: the service worker will serve from cache and then check if a new version is available. It can then force the refresh, or ask the user if he/she wants it immediately or later.

It even allows to go offline, as everything is cached!

Angular offers a dedicated package called @angular/service-worker. It’s a small package, but filled with cool features. Did you know that if you add it to your Angular CLI application, and turn a flag on ("serviceWorker": true in angular.json), the CLI will automatically generate all the necessary stuff to cache your static assets by default? And it will only download what has changed when you deploy a new version, allowing blazing fast application start!

But it can even go further, allowing to cache external resources (like fonts, icons from a CDN…), route redirection and even dynamic content caching (like calls to your API), with different strategies possible (always fetch for fresh data, or always serve from cache for speed…). The package also offers a module called ServiceWorkerModule that you can use in your application to react to push events and notifications!

This is quite easy to setup, and a quick win for your reload start time. It’s also one of the steps to build a Progressive Web App, and to score a perfect 100% on Lighthouse, so you should check it out.

If you enjoyed this blog post, you may want to dig deeper with our ebook, and/or with a complete exercise that we added in our online training. The exercise takes an application and walks you through what we would do to optimize it, measuring the benefits of each steps, showing you how to avoid the common traps, how to test the optimized application, etc. Check it out if you want to learn more!

See you soon for part 3!


What's new in Angular CLI 6.2?

Angular CLI 6.2.0 is out (in fact we even have a 6.2.1 available)!

If you want to upgrade to 6.2.1 without pain (or to any other version, by the way), I have created a Github project to help: angular-cli-diff. Choose the version you’re currently using (6.0.0 for example), and the target version (6.2.1 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/6.0.0…6.2.1. You have no excuse for staying behind anymore!

Let’s see what we’ve got!

Linter

The first thing is not really a new feature, but rather a bugfix, but it was annoying me, so I’m glad it landed!

With the previous CLI versions, if you ran ng lint, the linter was executed on every application in the project (usually your main application and the e2e application). Now, TSLint comes with a super awesome option called --fix, which automatically fixes some of the issues it found, I love it. And you can use it with the CLI! But running ng lint --fix was failing with the previous versions because it couldn’t figure if you wanted to run it on your main application or the e2e application… So you had to run ng lint app --fix and then ng lint app-e2e --fix.

This is now solved, and if you run ng lint --fix, the task will be executed on all your applications!

The fix is slightly more general than that, and this kind of command will now execute on all your applications if it is possible.

You can also now simply run:

ng lint src/app/app.component.ts

if you want to lint just a file.

To conclude this part about the linter, an option that disappeared in CLI 6.0 but existed before is also back: --lint-fix. This option can be used with every schematic, and will automatically fix the lint issues in the new generated files. You might be wondering why that would be useful: aren’t the files generated by the CLI already correct? They are indeed, but they use the default tslint.json. So if you have defined a different preference for TSLint for example to use double quotes instead of single quotes for strings, then by using this option, the generated files will automatically use your preferences.

ng generate component pony --lint-fix

Watch mode for libraries

As you hopefully know if you read our article about the release of Angular CLI 6.0.0, it is now possible to have multiple applications and libraries in your CLI project. But, as I noted in the article, a slightly annoying thing was that, when you made a change to the library source, you had to rebuild it manually if you wanted the rest of the project to see it, because there was no watch mode for ng build in a library.

That’s now no longer the case, and you can use ng build --watch for a library too, so the rest of your project will see the modifications without any manual steps anymore!

Ivy support

Angular 7 is still some weeks/months away, but the CLI is getting ready for the big novelty of this release: the new Ivy renderer (check out our previous article about Ivy).

You can give Ivy a try by generating a new application with:

ng new my-app --experimental-ivy

This will generate a new application with a few options activated for Ivy. It mainly adds in tsconfig.app.json:

"angularCompilerOptions": {
  "enableIvy": "ngtsc"
}

to activate Ivy. Be warned though, this is still very experimental!

That’s all for this small release, but the CLI team is already working on CLI 7.0, with some cool features incoming (an interactive prompt for the command, a better minifier, support of Angular 7…). Stay tuned!

All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!


Posts plus anciens