Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Accelerating Angular Development with Ivy

You're reading from   Accelerating Angular Development with Ivy A practical guide to building faster and more testable Angular apps with the new Ivy engine

Arrow left icon
Product type Paperback
Published in Oct 2021
Publisher Packt
ISBN-13 9781800205215
Length 242 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Authors (3):
Arrow left icon
Lars Gyrup Brink Nielsen Lars Gyrup Brink Nielsen
Author Profile Icon Lars Gyrup Brink Nielsen
Lars Gyrup Brink Nielsen
Jacob Andresen Jacob Andresen
Author Profile Icon Jacob Andresen
Jacob Andresen
Mateus Carniatto Mateus Carniatto
Author Profile Icon Mateus Carniatto
Mateus Carniatto
Arrow right icon
View More author details
Toc

Table of Contents (14) Chapters Close

Preface 1. Chapter 1: Discovering New APIs and Language Syntax 2. Chapter 2: Boosting Developer Productivity Through Tooling, Configuration, and Convenience FREE CHAPTER 3. Chapter 3: Introducing CSS Custom Properties and New Provider Scopes 4. Chapter 4: Exploring Angular Components Features 5. Chapter 5: Using CSS Custom Properties 6. Chapter 6: Using Angular Components 7. Chapter 7: Component Harnesses 8. Chapter 8: Additional Provider Scopes 9. Chapter 9: Debugging with the New Ivy Runtime APIs 10. Chapter 10: Using the Angular Compatibility Compiler 11. Chapter 11: Migrating Your Angular Application from View Engine to Ivy 12. Chapter 12: Embracing Ahead-of-Time Compilation 13. Other Books You May Enjoy

Leveling up our developer experience

Ivy improves the developer experience in many ways. In this section, we learn about the most noteworthy of them.

Improved compilation errors

Compile-time errors are a positive side effect of Angular using an AOT compiler. However, some of the build errors have needed additional context to aid in pinpointing the source of the error.

As an example, look at the error message in the following listing that is output when using an unknown element in an Angular application using View Engine:

ERROR in 'app-header' is not a known element:
1. If 'app-header' is an Angular component, then verify that it is part of this module.
2. If 'app-header' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<app-header></app-header>
<p>My content</p>
")

Which component has the error? How do we fix it?

The next listing shows the error message that is output for the same mistake in an Angular application using Ivy:

ERROR in src/app/app.component.html:1:1 - error NG8001: 'app-header' is not a known element:
1. If 'app-header' is an Angular component, then verify that it is part of this module.
2. If 'app-header' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
1 <app-header></app-header>
  ~~~~~~~~~~~~~~~~~~~~~~~~~
  src/app/app.component.ts:5:16
    5   templateUrl: './app.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component AppComponent.

The file path of the component model and the component template files are both listed, as well as the line number and the content of those lines. It is now much clearer where the problem was encountered—a big win for developer productivity.

Let's look at another example. If we accidentally add a duplicate comma to the imports array of an Angular module, as seen in the following code block, a build error will be output:

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, , CommonModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

View Engine outputs an error message similar to the one shown in the following listing:

ERROR in src/app/app.module.ts(11,27): Error during template compile of 'AppModule'
  Expression form not supported.
src/app/app.module.ts(11,27): Error during template compile of 'AppModule'
  Expression form not supported.
Cannot determine the module for class AppComponent in C:/projects/sandbox/angular-cli8-app/src/app/app.component.ts! Add AppComponent to the NgModule to fix it.

We get the relevant file and line number, but the error description, Expression form not supported, is not very helpful. Here is the equivalent error message output by Ivy:

ERROR in projects/second-app/src/app/app.module.ts:11:3 - error TS2322: Type '(typeof CommonModule | typeof BrowserModule | undefined)[]' is not assignable to type '(any[] | Type<any> | ModuleWithProviders<{}>)[]'.
  Type 'typeof CommonModule | typeof BrowserModule | undefined' is not assignable to type 'any[] | Type<any> | ModuleWithProviders<{}>'.
    Type 'undefined' is not assignable to type 'any[] | Type<any> | ModuleWithProviders<{}>'.
11   imports: [BrowserModule, , CommonModule],
     ~~~~~~~

In the previous listing, we immediately see that there is an issue in the imports array and that somehow, an undefined value ended up in it. Context is provided and the error description is improved.

Finally, let's look at the improved description of an error triggered by a piece of code that is not statically analyzable, as follows:

import { Component } from '@angular/core';
const template = location.href;
@Component({
  selector: 'app-root',
  styleUrls: ['./app.component.css'],
  template,
})
export class AppComponent {}

The template option in the previous example is not statically determinable as it relies on information only available at runtime. Here is the error message output by View Engine:

ERROR in No template specified for component AppComponent

In the previous listing, we see that the View Engine error message is for metadata that is not statically determinable. It tells us which component has an error, but it does not help us understand how to fix it. The type information shows that location.href is of type string, so why does AppComponent not have a template option according to the compiler?

The error message output by Ivy is a lot more helpful, as seen in the following listing:

ERROR in src/app/app.component.ts:8:3 - error NG1010: template must be a string
  Value could not be determined statically.
8   template,
    ~~~~~~~~
  src/app/app.component.ts:3:18
    3 const template = location.href;
                       ~~~~~~~~~~~~~
    Unable to evaluate this expression statically.
  node_modules/typescript/lib/lib.dom.d.ts:19441:13
    19441 declare var location: Location;
                      ~~~~~~~~~~~~~~~~~~
    A value for 'location' cannot be determined statically, as it is an external declaration.
src/app/app.module.ts:8:5 - error NG6001: The class 'AppComponent' is listed in the declarations of the NgModule 'AppModule', but is not a directive, a component, or a pipe. Either remove it from the NgModule's declarations, or add an appropriate Angular decorator.
8     AppComponent
      ~~~~~~~~~~~~
  src/app/app.component.ts:10:14
    10 export class AppComponent { }
                    ~~~~~~~~~~~~
    'AppComponent' is declared here.

The error message output by Ivy doesn't just show us the line and expression that are not statically determinable. It goes one step further and shows us that the entire location object is non-deterministic at compile time.

Read more about AOT limitations in Chapter 12, Embracing Ahead-of-Time Compilation.

Strict template type checking

View Engine had basic and full modes for template type checking. Ivy introduces strict template type checking. In addition to the full-mode template type checks, strict mode enables several checks, outlined as follows:

  • Property binding types are checked against their corresponding input property type.
  • Property binding type checks are strict about null and undefined values.
  • Generic types for components and directives are inferred and checked.
  • Checks the type of template context variables, including $implicit.
  • Checks the type of the $event template reference.
  • Checks the type of template references to DOM elements.
  • Safe navigation operations are type-checked.
  • Array and object literals in component templates are type-checked.
  • Attribute bindings are type-checked.

The strict check of null for property bindings is important for property bindings using AsyncPipe as it initially emits a null value. This means that input properties being used with AsyncPipe must either have a type that includes null or use the concepts known as template guards and input setter type hints.

An even better update experience

As part of Ivy, the Angular command-line interface (CLI) adds three improvements to the update experience.

When running the ng update command, the Angular CLI first downloads the latest stable version of the Angular CLI and uses it for the update to take advantage of the most recent improvements.

As part of the ng update command, automated migrations are run by the Angular CLI. For every migration, a message is shown, such as the example shown in the following listing:

** Executing migrations of package '@angular/core' **
> Static flag migration.
  Removes the `static` flag from dynamic queries.
  As of Angular 9, the "static" flag defaults to false and is no longer required for your view and content queries.
  Read more about this here: https://v9.angular.io/guide/migration-dynamic-flag
  Migration completed.

Finally, the --create-commits parameter flag is introduced to create a Git commit per migration to make it easier to debug the update process.

We will cover the Angular update process in more detail in Chapter 11, Migrating Your Angular Application from View Engine to Ivy.

Better IDE integration

Ivy introduces remarkable improvements to the Angular Language Service, which integrates with our IDE, such as VS Code.

Template and style Uniform Resource Locators (URLs) are verified inline, as seen in the following screenshot, where an error is displayed. This is especially helpful when renaming components:

Figure 2.1 – Invalid template URL error

Figure 2.1 – Invalid template URL error

Another neat improvement is that we can use the Go to definition IDE command to navigate to a component template or style sheet file. This makes it easier to work with one specific component.

Ivy versions of the Angular Language Service give us an additional context in tooltips for component models. The following screenshot shows a tooltip for a child component element in a component template. In the tooltip, we can see the Angular module that declared the child component. In the example, we see that ChildComponent is declared by AppModule:

Figure 2.2 – NgModule annotation in the component element tooltip

Figure 2.2 – NgModule annotation in the component element tooltip

Similarly, the tooltip that appears for a component model also shows the Angular module that declared this component, as seen in the next screenshot. Here, we see that AppComponent is declared by AppModule:

Figure 2.3 – NgModule annotation in the component model tooltip

Figure 2.3 – NgModule annotation in the component model tooltip

With Ivy, we can see method signatures in a tooltip, as seen in the following screenshot. This helps us reason about event handlers:

Figure 2.4 – Component method signature in the tooltip

Figure 2.4 – Component method signature in the tooltip

Ivy's Angular Language Service enables us to see type annotations of UI properties and the $implicit template reference. This allows us to get type information about an iterable UI property used with the NgFor directive, as seen in the following screenshot:

Figure 2.5 – Iterable UI property tooltip

Figure 2.5 – Iterable UI property tooltip

The next screenshot shows how Ivy enables us to get type information about the named iterator template reference in each loop cycle:

Figure 2.6 – Named iterator template reference tooltip

Figure 2.6 – Named iterator template reference tooltip

Combined with strict template type checking, as described earlier in this chapter, this allows us to catch type errors in components early and consistently.

The improved Angular Language Service released with Ivy adds syntax highlighting to inline component templates and styles, as seen in the following screenshot. This makes single-file components easier to use:

Figure 2.7 – Syntax highlighting for inline component template and styles

Figure 2.7 – Syntax highlighting for inline component template and styles

Inline templates even benefit from the ability to add syntax highlighting to template expressions also introduced with Ivy.

Finally, Ivy adds support for style preprocessors such as Sass in inline styles by introducing the inlineStyleLanguage option to the Angular @angular-devkit/build-angular:browser and @angular-devkit/build-angular:karma builders, for example: "inlineStyleLanguage": "scss".

You have been reading a chapter from
Accelerating Angular Development with Ivy
Published in: Oct 2021
Publisher: Packt
ISBN-13: 9781800205215
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime