Network aware preloading strategy in Angular
Tags: javascript, angular, webdev, typescript
Published: 2021-10-05 17:39:11

##Introduction

Preloading is great. It lets us fetch parts of our application before it is even requested for. By doing this, our content is ready to be served when needed without any delay. There are many ways of doing this, I'll be touching upon some of the ways to do this in Angular and how we can create our own custom preloading strategy based on the user's network state.

##Preloading strategies in Angular

Angular provides us with route-based preloading out of the box. There are two strategies namely `PreloadAllModules` and `NoPreloading`.

`NoPreloading`, as the name suggests does not preload any modules. This is the default behaviour.

`PreloadAllModules`, on the other hand, preloads all modules. A simple example adding a preloading strategy in a routing module file can be seen below

`app.routing.module.ts`

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vwqiwyljnr2g10j25l6.png) 
 

In the above code, the `ProductsModule` is lazily loaded, which means, the bundle is downloaded only when the user lands on the `/products` route. By passing the `preloadingStrategy` property, we instruct Angular to preload all lazily loaded modules.


##Custom preloading strategies

Angular also lets us provide custom preloading strategies where we can determine if a component needs to be preloaded or not. This can be done by providing our own custom class to the `preloadingStrategy` property.

Our custom class needs to extend `PreloadingStrategy` class from `@angular/router` and implement the `preload` function in it. A simple custom preloading strategy class would look something like this.

`customPreloadingStrategy.ts`
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1kqsgo5q3y523oydzt7.png)

Here, our `CustomPreloadingStrategy` class implements `PreloadingStrategy` class and has the `preload` function as well. The `preload` function should either return the `load` function or an empty observable. Returning the load function means the module can be loaded. As for the `shouldPreload` function, that is where our custom logic goes in. 

We can use this custom strategy in our routing module
`app.routing.module.ts`
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uagf7y1rx1dkvg17s40t.png)



##Network aware preloading strategy

Now that we are familiar with setting up a custom preloading strategy, now we can move on to using our user's network connection information to make a decision for us. Let's say our user has a very slow bandwidth, so we wouldn't want to further tax our user by preloading all of our modules in the background. In that case, we can decide not to preload our modules. To do this, we rely on the **navigator** object in our browser and specifically the **connection** property in navigator.

If you're reading this in desktop/laptop, open the browser's console and type in `navigator.connection`, you would see something like this.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgw7vyketqui48ic1wce.png)
 
We can leverage this information in our `shouldPreload` function to let Angular know whether to preload the module or not.

`customPreloadingStrategy.ts`

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvhg57yg84gt9v4gtjqs.png)

In the example above, we're using the `saveData` property to determine if the user has data-saver on, and we're using the `effectiveType` property to see if the user is on `2g` or `3g` connections. If the user is on slower internet connections, we are returning false, which would in turn prevent preloading of the particular module


##Conclusion

We can extend this idea of custom preloading strategies to make intelligent decisions based on our user's state. I have no idea if this method would even result in a tangible improvement in the user experience, but nevertheless a fun topic to explore.

You can find the source code [here](https://github.com/sidv93/ng-network-aware-preloading)

Cheers!