For over 5+ years we help companies reach their financial and branding goals. oDesk Software Co., Ltd is a values-driven technology agency dedicated

Gallery

Contacts

Address

108 Tran Dinh Xu, Nguyen Cu Trinh Ward, District 1, Ho Chi Minh City, Vietnam

E-Mail Address

info@odesk.me

Phone

(+84) 28 3636 7951

Hotline

(+84) 76 899 4959

oDesk Blog Website Responsive Websites Designing Websites Development

What’s New in Angular 10 ?

Angular 10 — the major release that spans the entire platform, including the framework, Angular Material, and the CLI — is available since June 24. Now, what does this mean?

Just like many members of the Angular community, I tried to follow the news and see what Angular 10 brought to us. I read many articles, but I felt like I’m a newbie in the programming world. My years of experience with Angular didn’t help me get a good understanding of what those articles were talking about.

So, I decided to write a new article presenting what’s new in Angular 10, making it all easier to digest.

Before I walk you through the most important changes and what they mean for you, your project, and the Angular landscape, I’ll explain a couple of interesting things and demystify the accompanying jargon. Let’s get started.

Lingo

Microsyntax

The Angular microsyntax lets you configure a directive in a compact, friendly string. The microsyntax parser translates that string into attributes on the <ng-template>. So instead of <ng-template ngFor [ngForOf]="items"><div>{{item}}</div></ng-template, you’ll write <div *ngFor="let item of items">{{item}}</div>.

Binding expression

There are four different types of data bindings available in Angular:

  • Event binding: Example: <button (click)="updateName()">Update button</button>
  • Two-way data binding: A mechanism where data flows both ways from the component to the view and back. The component and view are always in sync, and changes made on either end are immediately updated both ways. Example: <input [(ngModel)]="name">.
  • Interpolation: Text representing variables in components are placed in-between double curly braces in the template. Example: <p>{{ name }}</p>.
  • Property binding: A property binding is a one-way mechanism that lets you set the property of a view element. Example:
    <button [disabled]="buttonDisabled"></button>.

Abstract syntax tree (AST)

AST is an acronym for abstract syntax tree. It’s a representation of tokens generated from statements and expressions in a programming language. With the AST, the interpreter or the compiler can generate machine code or evaluate an instruction. The Angular template AST is a transformed and annotated version of the HTML AST that does the following:

  • Converts Angular template syntax shortcuts, such as *ngFor and [name], into their canonical versions (and bind-name)
  • Collects references (# attribute) and variables (let- attributes).
  • Parses and converts binding expressions in the binding expression AST using the variables and references collected

terser

terser is a JavaScript parser, mangler, and compressor toolkit for ES6+. The Angular CLI team moved to terser in Angular CLI 7.0 for the minification phase of the build because uglify-es is no longer maintained and uglify-js doesn’t support ES6+.

‘UrlMatcher’

UrlMatcher is a function for matching a route against URLs. You can implement a custom URL matcher for Route.matcher when a combination of path and pathMatch isn’t expressive enough.

type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) => UrlMatchResult;

The following matcher matches HTML files:

content_copyexport function htmlFiles(url: UrlSegment[]) {
  return url.length === 1 && url[0].path.endsWith('.html') ? ({consumed: url}) : null;
}export const routes = [{ matcher: htmlFiles, component: AnyComponent }];

Bazel

Bazel is a builder for the Angular CLI that was deprecated in version 10. Here are some reasons for this deprecation:

  • The Bazel ecosystem for the web is still evolving at a rapid pace
  • The introduction of the Angular Ivy compiler enables new ways to use Bazel in a faster and more efficient manner
  • Feature parity with the webpack-based Angular CLI is difficult to achieve without trade-offs that wouldn’t be acceptable for many Angular users

Angular Language Service

Angular Language Service is an analysis engine that integrates into your code editor and provides it with a way to get completions, tracing of references, errors, hints, and navigation inside Angular templates.

It works with external templates in separate HTML files and also with in-line templates. Your editor autodetects that you’re opening an Angular file. It then uses the Angular Language Service to read your tsconfig.json file, to find all the templates you have in your application, and then to provide language services for any templates you open.

It’s available as an extension for Visual Studio Code, WebStorm, and Sublime Text. You can install it by using the following command:

npm install --save-dev @angular/language-service

@angular/language-service is a wrapper around the TypeScript language service (much as ngtsc wraps tsc) and extends the analysis of TypeScript with a specific understanding of Angular concepts. It can bridge between the component class in Typescript and expressions in the templates.

Compiler Philosophy

Angular offers two ways to compile your application:

  • Just-in-Time (JIT), which compiles your app in the browser at runtime. This was the default until Angular 8.
  • Ahead-of-Time (AOT), which compiles your app and libraries at build time. This has been the default since Angular 9.

Ivy is a complete rewrite of the compiler (and runtime) in order to:

  • Reach better build times (with a more incremental compilation)
  • Reach better build sizes (with a generated code more compatible with tree shaking)
  • Unlock new potential features (metaprogramming or higher-order components, lazy loading of the component instead of modules, a new change detection system not based on Zone.js, etc..)

The View Engine is the predecessor of Ivy.

We can divide the work done on Ivy into three categories, as stated in the implementation status:

  1. @angular/compiler-cli: TypeScript transformer pipeline, which includes two command line tools: ngtsc and ngcc
  2. @angular/compiler: Ivy compiler which converts decorators into Ivy
  3. @angular/core: Decorators that can be converted by the @angular/compiler

To understand how the compiler is set up, it helps to understand the Typescript architecture under the hood.

TypeScript transpiler architecture

The following diagram shows the normal tsc flow and the steps to transpile a .ts file into a .js one. (tsc is from the Typescript CLI. It compiles the closest project defined by tsconfig.json.)

Here’s a brief explanation of this flow:

  • Parse: Atraditional recursive descent parser, tweaked a bit to support incremental parsing, that emits an AST. It’s a tree that helps to identify which files are imported in the current one.
  • Type checker: This step constructs a symbol table and then performs type analysis of every expression in the file, reporting errors it finds
  • Transform: A set of AST-to-AST transformations that perform various tasks, such as removing type declarations, lowering module and class declarations to ES5, converting async methods to state machines, etc.
  • Print: Conversion of TS to JS

Angular compilation steps

The Angular compiler is built on top of the regular TypeScript architecture and uses its three main phases: program creation, type checking, and emittance — plus an analysis step and a resolve step:

  • Program creation: Starts with tsconfig.json
  • Analysis: Goes through TS code class by class, looks for Angular things and gathering information about the structure
  • Resolve: Looks at the whole program at once, understanding it and making optimization decisions
  • Type checking: Just like the plain TypeScript compiler, it validates expressions in component templates and reports errors. This process isn’t extended or modified by ngtsc.
  • Emit: Generates Angular code for each decorated class and patches it. It converts TypeScript code to JavaScript. The most expensive operation of the whole process.

The two new compiler entry points

Angular has introduced two compiler entry points: ngtsc and ngcc.

ngtsc

ngtsc compiles Ivy-compatible code. It’s a TypeScript-to-JavaScript transpiler that looks for Angular decorators like @Component and substitutes them with their specific Angular runtime instructions/counterparts, like ɵɵdefineComponent. It’s a minimal wrapper around tscngc operates as ngtsc when the angularCompilerOption enableIvy flag is set to true in the tsconfig.json file.

Compilation flow

When ngtsc starts running, it first parses the tsconfig.json file and then creates a ts.Program. Several things need to happen before the transforms described above can run:

  • Metadata must be collected for input source files which contain decorators
  • Resource files listed in @Component decorators must be resolved asynchronously. The CLI, for example, may wish to run webpack to produce the .css input to the styleUrls property of a @Component.
  • Diagnostics must be run, which creates the TypeChecker and touches every node in the program (a decently expensive operation)

ngcc

ngcc stands for Angular compatibility compiler. It converts pre-Ivy modules (old style) to Ivy-compatible code. It processes code coming from npm and produces the equivalent Ivy version as if the code was compiled with ngtscngcc can also be run as part of a code loader like webpack to have packages from node_modules transpiled on the fly.

How to use ngcc

You can run ngcc after each installation of node_modules by adding a postinstall npm script:

{
    "scripts": {
        "postinstall": "ngcc"
    }
}

If you’re using Angular 8 — which was the first step for Ivy — and you want to start a new project with Ivy enabled, you can use the --enable-ivyflag with the ng new command:

ng new shiny-ivy-app --enable-ivy

The new project is automatically configured for Ivy. The enableIvy option is set to true in the project’stsconfig.app.json file:

"angularCompilerOptions": {
"enableIvy": true
}

And, finally, you can run the compiler by executing the ngc command inside of the newly created project folder:

node_modules/.bin/ngc

Then, you can inspect the generated code inside the dist/out-tsc folder.


Key Features of Angular 10

The upgrade to the Google-developed framework is focusing more on ecosystem improvements than new features. Angular 10 is set to be smaller than previous versions. The key features in the latest preliminary releases thus far include:

Features

  • In addition, optional stricter settings offer a more-strict project setup when creating a new workspace with ng new, via ng new -- strict. Enablng this flag initializes a new project with new settings to improve maintainability, help catch bugs, and allow the CLI to do advanced optimizations on an app.
  • language-service: A compiler interface has been added that wraps the actual ngtsc compiler. The language-service-specific compiler manages multiple typecheck files using the project interface, creating ScriptInfos as necessary.
  • language-service: Remove HTML entities’ autocompletion. Autocompletion is being removed from HTML entities, such as &amp;&lt;, etc., because it’s outside the core functionality of Angular LS, and it has questionable value and a performance cost.
  • Compiler: Name spans have been added for property reads and method calls
  • Compiler: Dependency information and ng-content selectors have been added to metadata. This proposed compiler feature would provide additional metadata useful for tools, such as the Angular Language Service, offering the ability to provide suggestions for directives/components defined in libraries.
  • Compiler: Propagation of the correct value span in an ExpressionBinding of a microsyntax expression to ParsedProperty, which, in turn, would propagate the span to the template ASTs (both VE and Ivy)
  • ngccAllow async locking timeouts to be configured. This adds support for the ngcc.config.js file for setting the retryAttempts and retryDelay options for the AsyncLocker. An integration test adds a new check for a timeout and uses ngcc.config.js to reduce the timeout time to prevent the test from taking too long.
  • ngccAprogram-based entry-point finder has been implemented. This finder is designed to only process entry points that are reachable by the program defined by a tsconfig.json file. Using this option can speed up processing in cases where there’s a large number of dependencies installed but only a small proportion of the entry points are actually imported into the application.
  • Bazel: Explicit mapping is being exposed from closure to dev-mode files. This feature is aimed at development tooling that has to translate production build inputs into their dev-mode equivalents.
  • Localize: Merging of multiple translation files is supported. Previously, only one translation file per locale could be loaded. Now users can specify multiple files per locale, and the translations from each of these files will be merged together by a message ID. The merging is on a first-wins approach. So if you have three files to be merged — "a.xlf”"b.xmb", and "c.json" — then any message from "a.xlf” will be used rather than a message from "b.xmb" or "c.json" … and so on. In practice, this means you should put the files in order of most important first, with fallback translations later.
  • Router: For the router, the CanLoad guard now can return Urltree. A CanLoad guard returning Urltree cancels the current navigation and redirects. This matches current behavior available to CanActivate guards that also has been added. This doesn’t affect preloading. A CanLoad guard blocks any preloading; any routes with a CanLoad guard won’t be preloaded, and the guards won’t be executed as part of preloading.
  • Angular Material: Angular Material now includes a new date range picker. To use the new date range picker, you can use the mat-date-range-inputand mat-date-range-picker components.

Performance improvements

  • compiler-cli: Perform template type checking incrementally and split Ivy template type checking into multiple files
  • ngcc: Immediate reporting of a stale lock file is now allowed. In addition, a parsed .tsconfig file is cached between runs.
  • ngcc: Reduce the size of the entry-point manifest file. The base path for package and entry points are known, so there’s no need to store these in the file. Storing empty arrays unnecessarily is avoided. Previously, even if an entry point didn’t need processing, ngcc would parse the files of the entry point to compute dependencies, which would take a lot of time for large node modules.
  • ngccTo improve performance, the computation of basePaths has been made lazy, so work is only done if needed in TargetedEntryPointFinder. Previously, basePaths was computed whenever the finder was instantiated, which was a waste of effort in the case when the targeted entry point had already been processed.

Breaking changes

  • Typescript 3.9 is now featured, with support for TypeScript 3.8 having been removed. TypeScript 3.6 and TypeScript 3.7 also are no longer supported.
  • TSlib, the runtime library for TypeScript containing helper functions, has been updated to v2.0.
  • The TSLint static analysis tool for TypeScript has been updated to v6.
  • Angular Package Format no longer includes ESM5 or FESM5 bundles, saving download and install time when running yarn or npm installfor Angular packages and libraries.
  • The browser configuration for new projects has been updated to exclude older, less-used browsers. Support is deprecated for Internet Explorer 9, Internet Explorer 10, and Internet Explorer Mobile.
  • Service workers: Previously, Vary headers would be taken into account when retrieving resources from the cache, completely preventing the retrieval of cached assets (due to ServiceWorker-implementation details) and leading to unpredictable behavior due to inconsistent/buggy implementations in different browsers. Now, Vary headers are ignored when retrieving resources from the ServiceWorker caches, which can result in resources being retrieved even when their headers are different. If your application needs to differentiate its responses based on request headers, please make sure the Angular ServiceWorker is configured to avoid caching the affected resources.
  • Router: Any resolver that returns EMPTY will cancel navigation. If you want to allow the navigation to continue, you’ll need to update the resolvers to emit some value, (i.e., defaultIfEmpty(...)of(..), etc).
  • Common: Logic has been updated concerning formatting day periods that cross midnight. When formatting a time with the b or B format code, the rendered string wasn’t properly handling day periods that spanned days. Instead, the logic was falling back to the default case of AM. This logic has been updated so it matches times within a day period that extends past midnight, so it’ll now render correct output, such as at night in the case of English. Applications using either formatDate() or DatePipe or the b and B format codes will be affected by this change.
  • Core: Warnings about unknown elements are now logged as errors. This won’t break your app, but it may trip up tools that expect nothing to be logged via console.error.
  • Core: Angular npm packages no longer containJSDoccomments to support the Closure Compiler’s advanced optimizations. The support for the Closure Compiler in Angular packages has been experimental and broken for quite some time. As of TS3.9, Closure is unusable with the JavaScript emit. For more information and updates, follow this link.
    If you used the Closure Compiler with Angular in the past, you’ll likely be better off consuming Angular packages built from sources directly rather than consuming the version on npm, which is primarily optimized for a webpack/Rollup + terser build pipeline. As a temporary workaround, you might consider using your current build pipeline with Closure flag --compilation_level=SIMPLE. This flag will ensure that your build pipeline produces buildable and runnable artifacts, at the cost of an increased payload size due to advanced optimizations being disabled.
  • Core: Generic has been made mandatory for ModuleWithProviders. A generic type parameter has been required for the ModuleWithProviders pattern to work with the Ivy compilation and rendering pipeline, but before this commit, View Engine allowed the generic type to be omitted. If a developer is using ModuleWithProviders without a generic type in your application code, a version 10 migration will update the code for you.

However, if a developer is using View Engine and, depending on a library that omits the generic type, you’ll now get a build-time error similar to:

error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).

In this case, ngcc won’t help you (because it’s Ivy-only), and the migration only covers application code. You should contact the library author to fix their library to provide a type parameter when they use this class. As a workaround, skipLibChecks could be set to false in the .tsconfig file or you can update your app to use Ivy.

Bug fixes

  • Router: UrlMatcher is now allowed to return null
  • Core: undecorated-classes-with-decorated-fields migration doesn’t decorate derived classes
  • Service workers: Prevent SW registration strategies from affecting app stabilization
  • A number of bug fixes have been made, including the compiler avoiding undefined expressions in a holey array and the core avoiding a migration error when a nonexistent symbol is imported. There’s also a workaround in the core for the terser inlining bug. Another bug fix properly identifies modules affected by overrides in TestBed.

The Compiler-Compatibility Problem

A compatibility functionality is needed to gradually migrate to Ivy without breaking changes. It ensures Ivy and non-Ivy libraries can coexist during the migration period.

Not all Angular code is compiled at the same time. Applications have dependencies on shared libraries, and those libraries are published on npm in their compiled formand not as TypeScript source code. Even if an application is built using ngtsc, its dependencies may not have been.

If a particular library wasn’t compiled with ngtsc, it doesn’t have reified decorator properties in its .js. Linking it against a dependency that wasn’t compiled in the same way will fail at runtime.

Converting pre-Ivy code

Since Ivy code can only be linked against other Ivy code, to build the application, all pre-Ivy dependencies from npm must be converted to Ivy dependencies. This transformation must happen as a precursor to running ngtsc on the application, and future compilation and linking operations need to be made against this transformed version of the dependencies.

Upgrade to Angular 10

To update your current Angular install, you can run this command (see the Angular Update Guide here):

ng update @angular/cli @angular/core

You can find Angular 10 releases on GitHub and more details in the changelog.

Thanks for reading. I hope this was helpful. If you have any questions, feel free to leave a response.

Lee Luong – Co-Founder & CEO

Author

oDesk Software

Leave a comment