Originally published by Minko Gechev at https://blog.angular.io
This post, contains a list of new tools and practices that can help us build faster Angular apps and monitor their performance over time. In each section, you’ll find links for further reference on how to incorporate them in your project. The focus of this post is on decreasing initial load time and speeding up page navigation using code-splitting and preloading.
We’ll look at the following topics:
One of the most expensive types of assets in an app is JavaScript. Once the browser downloads a JavaScript file, it often has to decompress it, after that parse it, and finally execute it. That is why it’s critical for the performance of an app to ship fewer bytes of JavaScript during the initial load time.
There are variety of practices we can apply to shrink our bundles. Two of the most popular ones are:
The Angular CLI has been doing a great job minifying bundles and eliminating dead code. In version 8, the CLI also introduced differential loading support, which can reduce the amount of JavaScript for modern browsers even further. All this is completely automated by the tooling Angular provides.
On the other hand, code-splitting is entirely in our hands. The next section is dedicated on how to shrink our JavaScript bundles by using this technique.
There are two main approaches to code-splitting:
The main difference between these two techniques is that with component level code-splitting, we can load individual components lazily even without a route navigation. For example, we can load the component associated with a chatbox only after the user clicks on a placeholder.
With route level code-splitting, we load the individual routes lazily. For example, if the user is in the home page of an app and they navigate to the settings page, Angular will first download the corresponding bundle and after that render the route.
Component level code-splitting
Component level code-splitting has been hard in Angular because of the factories that the current version of the Angular compiler generates. The good news is that Ivy will enable simpler mechanism for it. In the future releases of the framework, we’ll work on using these capabilities to deliver ergonomic APIs for component level code-splitting. Until then, there are two community libraries you can use to achieve ergonomic code-splitting on a component level:
Route-level code-splitting
Now let’s focus on route-level code-splitting. You can learn more about it here. This technique involves boilerplate code. To create a lazy route manually, we need to:
loadChildren
, declare a lazy route in a parent moduleWith Angular CLI version 8.1, you can now achieve this with a single command! To generate a lazy module use:
ng g module [module name] --route [route name] --module [parent module]
For example:
ng g module ranking --route ranking --module app.module
The command above will:
RankingModule
app.module.ts
RankingModule
Once we introduce a lazy route in our app, when the user navigates to it, Angular will first download the corresponding bundle from the network. On a slow internet connection, this could lead to a bad UX.
To work around that, Angular provides router’s preloading strategy.
There’s a built-in strategy that preloads all the modules in the application. You can use it by configuring the Angular router:
import { PreloadAllModules } from '@angular/router';// …
RouteModule.forRoot(ROUTES, { preloadingStrategy: PreloadAllModules })
// …
Preloading of JavaScript
The risk with this strategy is that in an application with many modules, it may increase the network consumption and also block the main thread when Angular registers the routes of the preloaded modules.
For larger apps, we can apply more advanced preloading heuristics:
The Angular implementation of the quicklink preloading strategy is ngx-quicklink. You can find a detailed guide on how to use it here.
Predictive prefetching uses a report for your app’s usage. You can find how to introduce predictive prefetching with Guess.js to your Angular CLI app in the video below:
Add Guess.js to an Angular CLI project
Code-splitting can greatly improve the performance of our apps but it doesn’t provide us with any guarantees that it won’t regress over time. For this purpose, we can use performance budgets.
To monitor our apps over time, the Angular CLI supports performance budgets. The budgets allow us to specify limits in which the production bundles of our app can grow. In the workspace configuration, under the budgets
section, we can specify several different types of budgets:
Budget types in the Angular CLI
All of them accept maximumWarning
and maximumError
. If we exceed the budget’s maximumWarning
value, the CLI will show a warning. If we exceed the maximumError
value, the build will fail.
Here’s a short video which shows how to quickly setup budgets for your project:
It’s very convenient to introduce budgets as part of your CI so that you can keep track of them across code changes. Read more about this here.
Looking at datasets of a lot of Angular apps running into the wild, we noticed that over 25% of them do not use content compression. Even more, don’t use a Content Delivery Network (CDN). These are two easy wins that are very simple to implement as part of the deployment pipeline.
To allow developers to ship fast Angular apps from end-to-end as part of Angular CLI version 8.3 we’ll introduce a new command called deploy
. By simply running ng deploy
, you’ll be able to:
We’ve been working very closely with Google Cloud & Firebase, Azure, and Zeit to introduce deployment capabilities for their platforms directly from the CLI. There are also third-party packages for Netlify and GitHub pages.
The list of packages available at the moment of writing of this article are:
@angular/fire
@azure/ng-deploy
@zeit/ng-deploy
@netlify-builder/deploy
angular-cli-ghpages
You can use them by running:
ng add [package name]
ng deploy
For example:
ng add @angular/fire
ng deploy
In this post we looked at few practical approaches to speed up an Angular app.
We saw how to reduce the size of our JavaScript bundles using component-level and route-level code-splitting. As the next step, we discussed preloading strategies that can speed up page navigation. To monitor our app’s performance over time we introduced performance budgets.
Finally, we talked about efficient serving and the integration of CDN and content compression enabled cloud services with the Angular CLI.
Thanks for reading ❤
If you liked this post, share it with all of your programming buddies!
Follow us on Facebook | Twitter
☞ Best 50 Angular Interview Questions for Frontend Developers in 2019
☞ How to build a CRUD Web App with Angular 8.0
☞ React vs Angular: An In-depth Comparison
☞ React vs Angular vs Vue.js by Example
#angular #javascript #web-development