Some ways to improve the performance of Angular applications

Tram Ho

Angular is a popular framework for building single page web applications. The framework itself (the latest version) is well optimized thanks to the great team and community, but when it comes to performance, we should always think of a few things that can make our application. Runs fast and smoothly.

1. Optimize the main bundle with Lazy Loading

When we build the app in production without lazy loading we will probably see these files created in the dist directory:

polyfills.js is to make our application compatible with different browsers. Because we write code with the latest features and not all browsers support those features.

scripts.js contains the scripts that we declared in the script section of the angular.json file.

runtime.js is the webpack downloader. This file contains the necessary webpack utilities to download other files.

Styles.css contains all the styles we declare in the styles section of the angular.json file.

main.js contains all our code including components (ts, html and css codes), pipes, directives, services and all imported modules (including 3rd libraries).

As you can see, the main.js file will get bigger and bigger, this is a problem because to see the website browser the web page needs to download the main.js file, execute and display it on the page, that’s not only This can be a challenge for mobile users with slow internet access, but also on the Desktop.

The easiest way to solve this problem is to divide your application into multiple lazy modules. When we use the lazy modules for each module, the angular creates its own chunk and it will load until needed (usually by activating a roue).

To prove this, I created two components, app.component and second.component. Both are in app.module so there is no lazyload module here. App.component is very simple and has two buttons to navigate to Second.component and return to App.component.

However, the second component contains very large text (about 1 mb) in the template.

Because there is no laziness, when we build our application, we get a large main.js containing all the code from app.component and second.component.

Now in the network tab of chrome dev tools, we can see that main.js is too big (1.3 mb)

The problem is that most of the time users visit the main page, rather than a specific page, so loading all the code of other pages is not the best solution. We can create lazy module for the second component and that module will only be activated when needed (ie only when the user navigates to that page). This gives us very small main.js and thus loads the first page very quickly.

When we use lazy loading, after the build process, a new file will be created, such as 4.386205799sfghe4.js. That’s the chunk of the lazy module and it’s much faster than not using lazy. Now when we open the application, we find that main.js is very small (266 kb).

And only when we navigate to the second page do we see the new file (1 mb) loaded

However, partial loading in such a way will also affect performance as navigation will be slower. Fortunately Agular provides a way to solve this problem with PreloadingStrargety. We can say Angular to download the main module (main.js) and it is fully loaded and executed, only after loading the other lazy modules in backgroud, so when the user navigates to the lazy page, everything has been downloaded. For example:

So always consider using as many lazy modules as possible with some preloading strategy. This will keep your main.js small, which means downloading and rendering the main page faster.

So always consider using as many lazy modules as possible with some preloading strategy. This will keep your main.js small, which means downloading and rendering the main page faster.

2. Debug bundles with Webpack Bundle Analyzer

Even after dividing the application logic into multiple lazy modules, you get a large main bundle (large by personal definition I consider greater than 1 mb for medium sized applications). You can further optimize by using Webpack Bundle Analyzer. This npm package allows to visualize the size of the webpack output files with an interactive treemap. First of all install the plugin as dev dependency in your Angular project

Then modify your pack.json file by adding this line in the script section

Note that dist / stats.json may be different in your project. For example, if your bundle files are created in dist / browser, you need to modify the command dist / browser / stats.json Finally run

This will create a production build with statistics about each bundle and with the help of the bundle webpack analyzer, we can imagine that with a scalable treemap.

From here we can see which modules / files are used in the bundle. This helps a lot when we can visually see what is included without having to be there.

3. Create small shared modules

The above shows us the best practice to have shared modules for DRY, but sometimes shared modules can also get bigger. For example, if we have a SharedModule containing a lot of mudule / component / pipe, importing that module in app.module will increase the package size of main.js, because we will import not only what the main module needs, but also All other unnecessary things come with SharedModule. To avoid this, we can create another shared module, HomeSharedModule will only contain the components that the main module and its components need. There are better shared modules than a large shared module.

4. Use Lazy Loading for images that do not display right on the page

When we load our main page for the first time, we may have images that are not visible to our users. User must scroll down to view image. However, images are downloaded immediately when we load the page, and if we have a lot of images, this can really affect performance. To solve this problem, we can Lazy load images, only load when users view them.

5. Use virtual scrolling for large lists

Version 7 of Franework introduces virtual scrolling in CDK. Virtual scrolling loads and unloads elements from the DOM based on the displayed parts of the list, making our application extremely fast.

6. Use FOUT instead of FOIT for fonts

In most websites, we find beautiful and custom fonts, instead of regular fonts. However, using custom or font provided by another service requires the browser to download and analyze the font when a user visits our site. There are two scenarios: what if we use custom fonts provided by 3rd party services like Google Fonts

  1. The browser waits to download the font, parse it, and only then display the text on the page. The text on the page will be invisible until the font is downloaded and parsed. This is FOIT, or Flash of invisible text.
  2. The browser initially displayed text in regular fonts and also tried to fetch external font styles. Once downloaded and parsed, it will exchange regular fonts with our custom fonts. The text on the page will be displayed in regular fonts, while if the browser will download and analyze the external font, the font will be swapped. This is FOUT or Flash of unstyled text.

Most browsers use FOIT and only Internet Explorer uses FOUT. To fix this, we can use the font display description for @ font-face and tell the browser if we want to go with regular fonts and then exchange or leave hidden text.

Most browsers use FOIT and only Internet Explorer uses FOUT. To fix this, we can use the font display description for @ font-face and tell the browser if we want to go with regular fonts and then exchange or leave hidden text. You can also read this article explaining how fonts work and in which cases you need FOIT and FOUT.

Conclude

So I’ve outlined a few ways to improve your Angular application performance, hopefully can help you at work.

Reference article: How to optimize Angular applications

Share the news now

Source : Viblo