Angular 12 Released
Angular v12 has been released! Here are some main updates.
Nullish coalescing operator support
@Component(){
selector: 'app-comp',
template: `<div>Hello, {{title ?? 'Angular'}}</div>`
})
Core
APP_INITIALIZER now supports Observable.
It is also a long-waited feature request: in Angular v12, we can now use Observable
as APP_INITIALIZER
.
import { APP_INITIALIZER } from '@angular/core';
function observableInitializer() {
// Before Angular v12, you have to return a Promise.
// return () => someObservable().toPromise();
// Now you can return the observable directly.
return () => someObservable();
}
@NgModule({
imports: [...],
providers: [{
provide: APP_INITIALIZER,
useFactory: observableInitializer,
multi: true
}],
...
})
export class AppModule {}
Http
HttpClient
Before Angular 12, if you wanted to pass boolean
or number
as HttpParams
, you had to:
HttpClient.get('api/endpoint', { param1: '10', param2: 'true' })
With Angular 12, the HttpParams
has been updated to accept the boolean
and the number
values:
HttpClient.get('api/endpoint', { param1: 10, param2: true })
Http Interceptor Context
This is a very long waited feature. In Angular 12, you can now pass data between interceptors. Here is a great article by Netanel Basal.
More readable Http status code
An enum HttpStatusCode
is provided, so the user can use this enum to write more readable code for status code check.
httpClient.post('api/endpoint', postBody, {observe: 'response'}).subscribe(res => { if (res.status === HttpStatusCode.Ok) { ... } });
Form
Form: Support min/max validator
HTML5 standards support built in validator such as min/max
for input
element.
<input type="number" min="5" max="10">
Before Angular 12, the min/max
attributes are ignored by FormsModule
, so the Angular FormControl valid
property will still be true even the input data exceed the min
or max
range. But the underlying DOM HTMLInputElement's validity.valid
will still be false.
From Angular 12, the min/max
validator is implemented so the valid
result will be consistent with native DOM status.
Animation
Sometimes we want to disable animations. Before Angular 12, we needed to provide the NoopAnimationModule
. In Angular 12, there is a new way to do that by using BrowserAnimationsModule.withConfig({disableAnimations: true})
so the user can disable animations based on the runtime information.
Router
Router: Support location.historyGo() functionality.
Support location.historyGo(relativePosition: number)
to navigate to the specific history page so it will be compatible with the DOM history.go() API.
Router: Provides RouterOutletContract interface
Provides RouterOutletContract
interface allows the 3rd party library to implement its own RouterOutlet
more easily (such as add own logic for navigation, animation). For details, please refer to this PR https://github.com/angular/angular/pull/40827.
Tooling
Angular Linker
Ivy has been released from Angular 9 and has become the default in the Angular App from Angular 10. It is fast, easy to debug, and has a lot of possibilities in the future. However, for Angular library development, the user still has to compile the lib with the old ViewEngine
to publish to npm
.
The Angular library deploy process is:
- The developer compiles the lib with
ViewEngine
. - When the Angular app is using the lib, when
yarn install
, Angular compiler will travel thenode_modules
directory and usengcc
to convert theViewEngine
library toIvy
. This process is slow and needs to run whenevernode_modules
changes.
The reason we need this process is if we remove ngcc
and publish the Ivy instructions
to npm, the instruction code will become the public API
. It is very difficult to change it in the future. ViewEngine
is not instruction but metadata, so it can be used across multiple versions even for Ivy
.
To resolve this issue, Angular provides an RFC last year, https://github.com/angular/angular/issues/38366, with an idea which is Angular Linker
. It is an advanced version ngcc
. It compiles the Angular library code with partial
mode.
- The output is not
Ivy
instructions, so it allows future changes. - The output is still
metadata
, but not likeViewEngine
, the metadata isself-contained
, so the output for one component contains all the information needed to compile this component without any other global knowledge(such asNgModule
). It is fast and be able to do incremental/cache/parallel build. - The new intermediate output can be directly consumed by Angular Compiler, so the
node_modules
folder doesn't need to be touched.
To use this feature, update the option in the tsconfig.lib.prod.json
like this.
"enableIvy": "true", "compilationMode": "partial"
Typescript 4.2 support
- Supports Typescript 4.2.
E2E protractor RFC
Angular is using protractor
for e2e
test. The protractor
has a long history from 2013
. It helped users write e2e
test, and to support better async
test, protractor
did a lot of work via ControlFlow to make async/await
work.
Since the native async/await
is introduced into Javascript standard, protractor
ControlFlow becomes incompatible with the native async/await
, so protractor
drops the ControlFlow and uses the solution of selenium-webdriver
completely.
Also protractor
has a lot of features just for AngularJS
such as locator/mock
. After removing these codes, protractor
becomes a wrapper of selenium wrapper
without any valuable functionalities.
And now the Angular developers are using several alternative solutions to do the e2e
test such as:
Cypress
PlayWright
Puppeteer
The Angular team posts an RFC to deprecate the protractor
and make Angular easy to integrate with the 3rd party e2d platform.
Here is the RFC https://github.com/angular/protractor/issues/5502
Based on the RFC, Angular plans to drop the protractor
support until Angular v15
and will guide the Angular developers to select an alternative platform when the user tries to run ng e2e
.
CLI: Webpack 5 support
Webpack 5 support many new features such as:
- Module federation is a new way to develop micro-frontend
- Disk caching for faster build
- Better tree shaking
CLI: Lint
Angular v11 deprecated to use TSLint
as the default linter, and Angular v12 remove TSLint
and codelyzer
from cli
, so please reference the following article to migrate to eslint
. (https://github.com/angular-eslint/angular-eslint#migrating-from-codelyzer-and-tslint)
CLI: Build
When we build an Angular app, we use ng build --prod
all the time. The options often confuse the user that --prod
will make a production build, but it is just an alias of ng build --configuration=production
. To make this more clear, CLI
remove --prod
and add a defaultConfiguration
setting with the value production
. Now, ng build
default will build with production configuration
.
CLI: Build bundles with ES2017+
Until Angular 12, Angular only supports output bundles in ES2015 format. ES2017+ is not supported because Zone.js
is not supporting native async/await
patching. From Angular 12, CLI supports to only transpile the native async/await
code to Promise
but keep the other ES2017+ code untouched, so you can specify the output bundle format to ES2017+ from Angular 12.
CLI: inlineCritical
by default
The inlineCritical
settings of styles optimization in the angular.json
becomes true by default. Please reference here for more details.
CLI: strict
mode by default
The workspace generated by CLI will use strict mode by default. To generate non-strict mode, use --no-strict
option.
CLI: Built in tailwindcss
support
Tailwindcss
is a popular CSS library. Before Angular 12, to integrate with Tailwindcss
, the user needs to do some postcss
configuration themselves. With Angular 12, this is done by the CLI
so it is super easy to do the integration.
npm install -D tailwindcss npx tailwindcss init
This is the same process to install the normal Tailwindcss
.
CLI: confirm ng add
before install packages from npm.
Now ng add
will ask the user to confirm the package/version before installing the packages. This gives the user a chance to stop the process when the user has a typo
in the project name or want to initialize the project with other options.
Angular Language Service for Ivy
Angular Ivy has been released since v9, but the Angular Language Service is still using View Engine
to compile the template and did a lot of magic
work to make everything work in Ivy
, which is not efficient. Also, since View Engine
is deprecated, some issues and features may not be implemented in the View Engine
version of Language Service for Ivy
.
Now we have the new Angular Language Service written in Ivy
and for Ivy
.
You can opt-in the new Angular Language Service beta with Ivy support now. To use it in VSCode
, try the following steps.
- Install the latest extension in the VSCode Marketplace
- Set strictTemplates: true in tsconfig.json Angular compiler options
- Go to Preferences -> Settings -> Extensions -> Angular Language Service -> Check “Experimental Ivy”
Please reference this blog for more details.
CLI: Support inlineStyleLanguage option
A new build option inlineStyleLanguage
is added. Now you can write css/sass/scss/less
in the inline style of a component!
Angular Components
MDC Web based new component
Angular Component is continuing to create new MDC Web based components and the backward-compatible. Here is the design.
For the new Angular Material Component
, Angular CDK
provides the behavior and the MDC Web Component
provides the user experiences defined by the Material Design
spec. The Angular Material
team doesn't need to maintain another implementation of the Material Design
and the UI will be more consistent.
New @use
SASS module system
You may already use the @import
syntax in the SASS style file, but it has some flaws and make the module system hard to maintain. For details, please reference the article here.
Now Angular Components
are using the new @use
syntax for the better module system
of SASS. To use the new module system, you can use the following schematic to migrate.
ng g @angular/material:themingApi
Also, the node-sass
package will be replaced by the new sass
package.
Deprecations
- IE11 support is deprecated!
ViewEngine
for application build is removed. All applications are usingIvy
to build.entryComponent
is removed fromComponent
schematic.string
based lazy loading support is dropped.
{ path: 'Lazy', component: LazyComponent }, { path: 'lazy', loadChildren: './modules/lazy/lazy.module#LazyModule', }
is not supported, please use dynamic import
instead.
{ path: 'Lazy', component: LazyComponent }, { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
For the full deprecation list, please check here.
How to update to v12
Use the Angular CLI:
ng update @angular/cli @angular/core
You can find more information from update.angular.io/.