What's new in Angular CLI 8.0?
Angular CLI 8.0.0 is out!✨
Of course this brings us the support of the brand new Angular 8.0 version, but also a lot of new features.
If you want to upgrade to 8.0.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 (7.2.1 for example), and the target version (8.0.0 for example), and it gives you a diff of all files created by the CLI: angular-cli-diff/compare/7.2.1…8.0.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 in this release!
Angular 8 and TypeScript 3.4 support
This was obviously expected: Angular 8.0 is now supported, and even required, by the CLI. Note that as Angular 8.0 now requires TypeScript 3.4, you will need to also update your TypeScript version. You can checkout out what TypeScript 3.3 and TypeScript 3.4 brings on the Microsoft blog.
The CLI now also supports the new style of lazy-loading declarations using TypeScript import
, introduced in Angular 8.0. It is even required if you want to use Ivy (see below).
So you can change your loadChildren
declarations from:
loadChildren: './admin/admin.module#AdminModule'
to:
loadChildren: () => import('./races/races.module').then(m => m.RacesModule)
The import
feature was introduced in TypeScript 2.4
and is similar to the ECMAScript standard.
If you want to use import
in your CLI project,
you must enable it by using "module": "esnext"
in the root tsconfig.json
file.
If you updated your CLI version by running ng update @angular/cli
you won’t even have to do it manually,
as an update schematic will automatically take care of it for you!
Differential loading
This is one of the cool new features of the CLI 8.0.0 as it allows to specify which browsers you want to target, and the CLI will automatically build the necessary JS bundles with the required polyfills for your targets.
A first step was done in this direction with CLI 7.3 and its conditional ES5 browser polyfill loading. This release goes one step further.
The default target in tsconfig.json
is now es2015
which means the default target of ng build
is now the modern browsers that support ES6 features.
But if you need to support older browsers like IE9,
then you can specify it by using the browserslist
file.
This file already exists in your CLI project but was use for the CSS part only.
It is now also used for the JS generation.
The default content is:
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
You can check out the details on the browserslist repository, but a cool trick is to run:
npx browserslist
in your project to see what your current browserslist
configuration actually means 🚀.
Or you can also check browserl.ist and enter your query.
The CLI uses this configuration to generate only one “modern” build if you only target modern browsers,
or build the application twice if you asked for IE 9-11 support for example.
The dist
directory then contains the same bundle twice after ng build --prod
:
index.html
main-es2015.407919b7ee8dd339e9bc.js // smaller version
main-es5.145b0a190c32187f268c.js // slightly bigger one
polyfills-es2015.40c67a1b836fd165fb67.js // 43Kb
polyfills-es5.b96063cf2c012927fe18.js // 110Kb
runtime-es2015.293c0dc955d5bcd5c818.js // same size
runtime-es5.645890afb0d6a6596d07.js // same size
The index.html
file references all of them,
but the es5
scripts are marked with the nomodule
attribute,
and the es2015
scripts have a type="module"
attribute.
The nomodule
attribute indicates to modern browsers (that supports ECMAScript modules)
to ignore this script,
so they are not even fetched on modern browsers.
And the older browsers will ignore the scripts with type="module"
.
So each browser loads only what it really needs,
with only older browsers downloading the extra JS needed.
The default configuration is the recommend one,
and will trigger the two builds.
You currently have to set a very restricted query to only have the es2015
build,
like > 4%
(to get rid of UC Browser for Android which is still used a lot).
Note that core-js
has been updated to v3,
and is now directly handled by the CLI itself,
so it’s no longer needed as a dependency of your application.
Also the property es5BrowserSupport
introduced
in CLI 7.3 is now unnecessary and has been deprecated.
dart-sass replaces node-sass
The CLI now uses dart-sass instead of node-sass to build your Sass files. The Dart implementation of Sass is now the reference implementation and has replaced the historic Ruby one. It is also notoriously faster.
It should not have an impact on the generated files, but there are some differences between the implementations and I heard that the compiler might be slightly stricter.
You can also install fibers
if you want to speed things up
(npm install --save-dev fibers
).
Vue CLI, which also recently migrated to dart-sass,
mentions that the compilation can be twice as fast with fibers
installed.
Note that all of this was already possible previously, but it is now the default,
and is technically a breaking change.
You can still use node-sass
if you wish, by installing it explicitly.
Ivy support
You probably know that the main feature in Angular 8.0 is Ivy. You can checkout our dedicated article to Ivy to learn more The CLI provides a switch to give it a try. You can test it in a new project with:
ng new project --enable-ivy
Or in a existing project by adding the following option in your tsconfig.app.json
file:
"angularCompilerOptions": {
"enableIvy": true
}
When using Ivy, you need to compile your third party Angular modules with ngcc
(the Angular Compatibility Compiler).
This tool generates the code necessary to compile your application with Ivy enabled (by generating the ɵcmp
field, ɵmod
field, etc. for each dependency you use).
But no need to worry about it, as the CLI now has a Webpack plugin that takes care of it for you! Your workflow will not change, even if behind the scenes the CLI does an extra-step for you when necessary.
If you give it a try, remember that the Ivy support is still quite new 😋.
Web worker support
This version provides a new generate
schematic
to add a Web Worker to one of your component.
This can be handy if you want to delegate a computational heavy task
to a dedicated thread in the browser
instead of blocking the main one.
Let’s say that your PictureComponent
(in src/app/picture
)
needs to do some CPU intensive work, like applying filters to an image.
You can run:
ng generate web-worker picture/picture
This will generate a new file called picture.worker.ts
in src/app/picture
,
containing the following boilerplate code:
addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});
That’s where you would put your heavy code computation.
and adds this other boilerplate code to your PictureComponent
:
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('./picture.worker', { type: 'module' });
worker.onmessage = ({ data }) => {
console.log(`page got message: ${data}`);
};
worker.postMessage('hello');
} else {
// Web Workers are not supported in this environment.
// You should add a fallback so that your program still executes correctly.
}
to get you started.
The sample posts a simple string, but you can post an object or an array. It will be serialized and then deserialized so the worker receives a copy.
The schematic will also configure your CLI project
if this is the first time you add a Web Worker.
It will exclude the worker.ts
files from your main TypeScript configuration,
and add a new TypeScript configuration named tsconfig.worker.json
that handles the worker.ts
file.
The angular.json
file is also modified to add:
"webWorkerTsConfig": "tsconfig.worker.json"
Then, when you’ll run ng build
, the CLI will package the Web Worker in a dedicated bundle (using googlechromelabs/worker-plugin).
Note that this is different from running Angular itself in a Web Worker
via @angular/platform-webworker
, which is not yet supported in Angular CLI.
Usage analytics data
The CLI can now collect usage analytics data. If you opt-in, some stats are collected and sent to the CLI team, to help them prioritize features and improvements. You can’t really miss this new feature, as you’ll be asked after installing the new CLI version globally 🧐.
You can opt-in with ng analytics on
.
A few metrics are collected if you opted in globally: command used, flags used, OS, Node version, CPU count and speed, RAM size, command initialization and execution time, and errors with their crash data if any occurs. If you opted-in in the project, it will even collect for build commands the number and size of your bundles (initial, lazy and total), the assets, polyfills and CSS sizes, and the number of ngOnInit
in your code.
If you use ng update
to update you CLI project,
you will be asked about whether you want to collect and send analytics or not (or when you install the CLI globally).
Would you like to share anonymous usage data with the Angular Team at Google under
Google’s Privacy Policy at https://policies.google.com/privacy? For more details and
how to change this setting, see http://angular.io/analytics.
You can manually trigger the prompt again with ng analytics prompt
. You can turn it off at any time with ng analytics off
.
You can find more details on the official documentation.
I think this will be really helpful for the CLI team, as they’ll have a real insight about what’s going on in the real world (build time, test time, build sizes, etc.).
It is also possible to gather these usage analytics in your own Google Analytics, to see how your teams are using the CLI.
This can be configured globally with ng config --global cli.analyticsSharing.tracking UA-123456-12
. More information about that can be found here.
Project layout change
You’ll notice that the project layout changed quite a bit:
- there is no more a dedicated project for e2e tests in the
angular.json
file - the
tsconfig.*.json
,karma.conf.js
files have migrated to the root of the workspace, and the relative paths they contained were updated to reflect that.
SVG templates support
It is now possible to have a file with an svg
extension as template (instead of only HTML previously).
This was the first PR from @oocx and he detailed the feature himself in an article that you can check if you want to learn more.
Codelyzer 5.0
The default TSLint configuration loads additional rules from the excellent Codelyzer,
which has recently been released in version 5.0.
As this new version of Codelyzer renames some of its rules,
the CLI offers a schematic to automatically update your TSLint configuration
when you upgrade using ng update @angular/cli
.
Note that Codelyzer v5 also offers new rules and deprecated some,
take a look at the changelog if you want to learn more.
The update schematic will also removes the es6 imports from your polyfills.ts
file,
as they are now added automatically if needed by the CLI (see our article about CLI 7.3).
NPM/PNPM support
After NPM and Yarn, The CLI now supports another package manager: PNPM.
Also note that the ng add
command gained a new --registry
flag,
allowing to add packages from a private NPM registry (ng update
already offered it).
New Architect API
This is just a note about the internals of the CLI. The Architect API, responsible for running pretty much everything under the hood, has been completely overhauled. Check out this blog post on the official Angular blog if you want to learn more about it.
As you can see, this 8.0 release was packed with new features!
All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!