Angular is the most popular framework for developing single-page web applications, although this does not mean that Angular applications can contain only one page. With this framework, you can create sites consisting of dozens of pages. The latest version of Angular, thanks to the efforts of the development team and the community of enthusiasts, is well optimized. However, when it comes to a specific application, we must not forget about some things that affect its performance.

In the material, the translation of which we publish today, six directions of optimization of Angular-applications will be revealed.
1. Lazy loading and optimization of the main bundle
If the lazy loading is not used when preparing the production version of the application, then you will most likely see the following files in the
dist
folder.
')
polyfills.js scripts.js runtime.js styles.css main.js
The
polyfills.js
file allows
polyfills.js
to ensure the compatibility of an application written using the latest features of web technologies with various browsers.
The
script.js
file contains the scripts described in the
scripts
section of the
angular.json
file. Here is a simple example of such a section.
"scripts": [ "myScript.js", ]
The
runtime.js
file is a Webpack loader. It contains the Webpack tools needed to download other files.
The
styles.css
file contains styles declared in the
styles
section of the
angular.json
file. Here is an example of this section.
"styles": [ "src/styles.css", "src/my-custom.css" ],
The
main.js
file stores all application code, including components (TS, HTML and CSS code), pipelines, directives, services, and imported modules (including third-party modules).
As the application grows and
main.j
size of the
main.j
s file also
main.j
. This can turn into a problem, because, in order to form a page, the browser, besides solving other data visualization tasks, needs to load and parse the
main.js
file. If this file is large enough, its processing will be a difficult task not only for mobile, but also for desktop browsers.
The easiest way to solve this problem is by dividing the application into several modules, with which the lazy loading technique is used. With this approach, Angular generates a separate file for each module, which will not be loaded until it becomes necessary (usually, when a certain route is activated).
In order to demonstrate the use of lazy loading techniques, two components were created -
app.component
and
second.component
. Both of them are in the
app.module
module, lazy loading does not apply when working with them.
The
app.component
component
app.component
extremely simple. It displays two buttons, one of which is responsible for the transition to the
second.component
, and the second leads back to the
app.component
.
Component AppThe
Second
component template contains a very large fragment of text with a volume of approximately 1 MB.
Second componentSince the lazy loading technique does not apply here, our application will have a large-sized
main.js
file containing the
app.component
and
second.component
.
If you open the Chrome developer tools and look at the Network tab, you can estimate the size of the
main.js
file. Namely, it is 1.3 MB.
File Size Analysis with Chrome Developer ToolsThe problem here is that most of the time when working with our project, the user will be on his main page, and not on some other one, so downloading all the code as a single file is not the best idea. The code of the second component can be transferred to a separate module, which will be loaded only if the user navigates to the appropriate page. This is reflected in a significant decrease in the
main.js
file, which gives a very quick first load of the main page of the site.
When using the lazy loading technique, after the project build process is completed, a file like
4.386205799sfghe4.js
will be created. This is where the code that does not load when the site first loads will be stored. As a result, if you now open the site and analyze it, it turns out that the size of
main.js
is only 266 KB.
Reducing the size of main.jsA large additional file of 1 MB in size is loaded only after moving to the appropriate page.
Download additional fileWe applied the lazy download, but we cannot say that this solution suits us completely. The fact is that such an approach slows down the user's first transition to the page, for output of which a separate large file is needed. Fortunately, Angular provides a means to solve this problem. Namely, we are talking about technology
PreloadingStrategy .
Using it, we can tell the framework that, after the main module (
main.js
file) has been loaded and processed, it would load, in the background, other modules. As a result, when the user navigates to a page that previously needed to download a large file, it turns out that this file has already been downloaded. Here is a sample code to preload all modules.
import { PreloadAllModules, RouterModule } from '@angular/router'; RouterModule.forRoot( [ { path: 'second', loadChildren: './second/second.module#SecondModule' } ], {preloadingStrategy: PreloadAllModules})
When applying lazy loading when optimizing Angular applications, it is recommended to strive to break the project into as many modules as possible. In addition, you need to pay attention to their preloading. This will allow the
main.js
file to be small in size, which means faster loading and displaying of the project’s main page.
2. Analysis of bundles using Webpack Bundle Analyzer
If even after dividing the project logic into multiple modules, it turns out that
main.js
is still too large (for small and medium-sized applications, the author of this material suggests to consider a large 1 MB file), you can continue to optimize the application using the Webpack Bundle Analyzer. This npm package allows you to visualize the results of the Webpack work in the form of a tree structure that supports zooming the view. In order to use the Webpack Bundle Analyzer, we will install it in the Angular project as a development dependency.
npm install --save-dev webpack-bundle-analyzer
Then we modify the
script
section of the
package.json
file, adding the following text to it.
"bundle-report": "ng build --prod --stats-json && webpack-bundle-analyzer dist/stats.json"
Please note that the address of the
dist/stats.json
may be different in your project. For example, if you have ready bundle files in the
dist/browser
folder, you will need to rewrite the above line like this:
dist/browser/stats.json
.
Now run the analyzer.
npm run bundle-report
After executing this command, the production assembly of the application will be generated and the statistics for each bundle will be displayed. Here is the result of the visualization of this data.
Project analysis using Webpack Bundle AnalyzerNow you can analyze the composition of each bundle. This is a very useful tool that allows you to identify dependencies, without which you can do.
3. Create several small modules for sharing
Modules that share different parts of an application contribute to the implementation of the
DRY principle, but sometimes even such modules, as the application develops, become more and more. For example, if we have a certain
SharedModule
module containing many other modules, components, pipelines, importing such a module into
app.module
will increase the size of the
main.js
bundle, since such a move will not only lead to the import of what
main.js
needs, but also all that is in the
SharedModule
. In order to avoid this situation, you can create another module, something like
HomeSharedModule
, designed to be shared by the main module and its components.
The presence in the project of several modules intended for sharing is better than the presence of only one such module, usually having large dimensions.
4. Using lazy loading for images that are not visible on the page.
When you first load the main page of the application, it may be that there are images on it that are not visible to the user (they are outside the viewing area). In order to see them, you need to scroll the page. But these invisible images are loaded when the page loads. If there are a lot of them, it will affect the page loading speed. In order to cope with this problem, you can apply a lazy loading technique to images, loading them only when the user gets to them. There is one useful JS tool,
Intersection Observer , which makes it easy to implement lazy loading of images. Moreover, in order to reuse, on the basis of it you can create an appropriate directive. Details about this can be found
here .
5. Using virtual scrolling for long lists
In the seventh version of Angular there is the possibility of using
virtual scrolling . This technology loads elements into the DOM and unloads them based on how much of the list is visible to the user. This greatly speeds up the work of applications that use long lists.
Only visible list items are displayed on the page.6. Use of FOUT strategy for working with fonts instead of FOIT strategy
Many sites use non-standard fonts. They usually look very attractive, but their use creates an additional load on the browser, as it has to download these fonts and prepare them for work. When using non-standard fonts, say, downloaded from a third-party service like Google Fonts, the following two scenarios are possible:
- The browser loads the font, processes it and only then displays the text. Until the font is ready for use, the text typed in this font will be invisible. This is called FOIT (Flash of invisible text).
- The browser initially displays text using a standard font, while performing the loading of the external font. When this font is ready for use, the standard font changes to that particular font. As a result, it turns out that the text on the page will be displayed in a standard font until a special font is loaded, after which the text will be displayed again, but in a new font. This is called FOUT (Flash of unstyled text).
Most browsers use the FOIT strategy when working with non-standard fonts, the FOUT strategy is used only in Internet Explorer. In order to use FOUT instead of FOIT, you can use the
font-display
descriptor for
@font-face
, and tell the browser whether we want the text to appear first in standard font, and then ours, or if we are satisfied with a certain invisibility period of the text . If you are interested in the topic of fonts - take a look at
this material. In particular, here you can find information about the features of the work of the fonts and recommendations regarding the choice of the FOIT or FOUT strategy.
Results
Here we looked at several techniques for optimizing Angular applications. In fact, there are many more. In particular, we are talking about server rendering, the use of service workers, AMP pages. The expediency of optimization and the choice of its methods depend on the specific project - on its features and goals.
Dear readers! What approaches do you use to optimize Angular applications?
