📜 ⬆️ ⬇️

Angular Application Optimization

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 App

The Second component template contains a very large fragment of text with a volume of approximately 1 MB.


Second component

Since 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 Tools

The 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.js

A large additional file of 1 MB in size is loaded only after moving to the appropriate page.


Download additional file

We 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 Analyzer

Now 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:

  1. 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).
  2. 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?

Source: https://habr.com/ru/post/431876/


All Articles