I have lazy loading implemented. I'm trying to set up a custom preloading strategy.
Say I have the following url structure:
/
/fruit
/fruit/bananas
/fruit/apples
/vegetables
If I hit /
, I want to preload /fruit
. Following the Angular example, I simply put data: {preload: true}
in my route config, and then implement a custom preloading strategy which checks that data and loads. This works fine.
However, I don't want to preload /bananas
or /apples
until I actually navigate to /fruit
. As it is, as soon as /fruit
is preloaded, the preloading strategy finds more modules with {preload: true}
and preloads /bananas
and /apples
too.
Is there a clean way to put off preloading modules after their parent modules have been navigated to?
The Angular router provides a configuration property called preloadingStrategy , which defines the logic for preloading and processing lazy-loaded Angular modules. We'll cover two possible strategies: PreloadAllModules , which preloads all lazy-loaded routes, as the name implies.
Lazy loading is the process of loading components, modules, or other assets of a website as they're required. Since Angular creates a SPA (Single Page Application), all of its components are loaded at once. This means that a lot of unnecessary libraries or modules might be loaded as well.
Use LoadChildren:For lazy loading. Using this property will optimize your application's performance by only loading the nested route subtree when a user navigates to a particular URL that matches the current route path. It helps in keeping the nested routes table separate.
I ended up doing a custom but scalable solution using the route's data
property. I created 3 properties:
preload
(boolean) - if true, preload as soon as Angular knows about it (like /fruit
). This is the basic example Angular gave us in their docspreloadCheckpoint
(enum) - I define each app "checkpoint" in my own enum. So in my question's example, /fruit
is the checkpoint, and I'd define on it data: {preloadCheckpoint: myCheckpointEnum.FRUIT}
preloadAfterCheckpoint
(enum) - I define this to put off preloading until a certain checkpoint is reached. If I define this on /bananas
, the bananas module won't load until the route with the FRUIT
checkpoint is definedI subscribe to route changes so I can keep my checkpoints list updated, and then check that list during every preload attempt.
export class CustomPreloadingStrategy implements PreloadingStrategy {
checkpoints: Set<PreloadCheckpoints> = new Set<PreloadCheckpoints>();
constructor(router: Router, route: ActivatedRoute){
router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => route),
map(route => {
while (route.firstChild) route = route.firstChild; //gets the deepest child
return route;
}),
filter(route => route.outlet === 'primary'))
.subscribe((route) => {
if(route.snapshot.data['preloadCheckpoint'] !== undefined){
this.checkpoints.add(route.snapshot.data['preloadCheckpoint']);
}
});
}
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data && ( route.data['preload'] || this.checkpoints.has(route.data['preloadAfterCheckpoint']) )){
return load(); //preload this route
} else {
return of(null);
}
}
}
export enum PreloadCheckpoints {
FRUIT
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With