With the discharge of standalone parts / elective modules in Angular 14, I have been making an attempt to dip my toe again within the Angular pool. However, as I used to be studying up on the Router’s loadChildren
property for lazy-loading routes, one thing within the documentation struck me as odd. It states that the loadChildren
property wants to make use of the Fats-arrow syntax:
LoadChildrenCallback
(kind alias): A perform that known as to resolve a set of lazy-loaded routes. Have to be an arrow perform of the next kind:
() => import('...').then(mod => mod.MODULE)
or() => import('...').then(mod => mod.ROUTES)
The rationale this appeared like an odd requirement is as a result of a Fats-arrow perform is only a perform. It would not truly do something completely different than a standard perform
declaration / expression different then retain the this
binding; and, relying on the way it’s authored, can create an implied return
assertion. However, these aspects are as much as the discretion of the developer writing the code – it ought to have completely no bearing in any respect on how that code is being consumed.
To exhibit, let’s outline a Route[]
assortment that doesn’t use the Fats-arrow syntax when lazy-loading a sub-tree of the router configuration. Within the following routes file, the /admin
path goes to be lazy-loaded:
// Import core Angular modules.
import { Route } from "@angular/router";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
/**
* NOTE ABOUT IMPORT(): Whereas the native import() perform is able to loading a dynamic
* path, all import paths inside our Angular utility should be static. It is because
* Webpack performs a static evaluation of the import() calls at BUILD TIME and subsequently
* can not eat paths which might be outlined at RUNTIME. The Angular documentation additionally states
* that the loadChilren() name should use a FAT-ARROW perform; nonetheless, this isn't true.
* The loadChildren() name can use a traditional Operate so long as it returns the results of a
* static import() name. I believe that the Fats-Arrow constraint within the documentation is
* extra about making the road of code LOOK as if it had been an inline name as an alternative of deferred
* name.
*
* See GitHub: https://github.com/webpack/webpack/points/6680
*/
export var ROUTES: Route[] = [
{
path: "admin",
loadChildren: function lazy() {
return( getRoutes( import( "./admin-view/admin-view.routes" ) ) );
}
}
];
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
/**
* I present a technique that simplifies the lazy-loading of routes from the given path.
*/
export async perform getRoutes(
routesPromise: Promise<any>,
routesKey: string = "ROUTES"
) : Promise<Route[]> {
var mod = await routesPromise;
return( mod[ routesKey ] );
}
As you possibly can see, there is not any Fats-arrow perform anyplace on this file. There’s merely a Callback being outlined utilizing a “conventional” perform
expression. Inside that callback, I am then invoking the native import()
perform to load the Admin’s routes file and I am utilizing the getRoutes()
helper perform to “unwrap” the resultant Promise
.
And, after we run this Angular 14 code and navigate to the /admin
route, we will see the routes file get lazy-loaded within the community:

After all, in some instances, the Fats-arrow perform can be utilized for nothing extra than to scale back the quantity of code on the display screen. The above code could be rewritten to be barely extra concise (the general code on this snippet is being truncated to spotlight variations):
export var ROUTES: Route[] = [
{
path: "admin",
loadChildren: () => getRoutes( import( "./admin-view/admin-view.routes" ) )
}
];
This is similar actual factor. Solely, I am utilizing the Fats-arrow syntax as a comfort in an effort to take away the Operate’s body-brackets and express return
assertion. And, I am nonetheless utilizing the getRoutes()
helper perform as a method to cover the Promise
dealing with / unwrapping.
Usually, I’m extraordinarily turned-off by “one liner” Fats-arrow capabilities. I discover them arduous to learn and arduous to debug since there’s little or no “wiggle room” for added expressions. However, on this case, I are inclined to agree that it makes the code a bit extra readable because it removes a lot of boiler-plate syntax and makes the essentially deferred import()
invocation really feel extra collocated with the route.
import()
Calls at Construct Time
Webpack Performs a Static Evaluation of When you outline just a few routes this manner, it is pure to see a sample emerge. And, it is pure to wish to additional clear issues up by making a Manufacturing unit perform that takes the file path and generates the loadChildren
callback. One thing akin to:
export var ROUTES: Route[] = [
{
path: "admin",
// !!!!!!!!!! CAUTION: THIS DOES NOT WORK !!!!!!!!!! //
// !!!!!!!!!! CAUTION: THIS DOES NOT WORK !!!!!!!!!! //
loadChildren: lazyLoad( "./admin-view/admin-view.routes" )
// !!!!!!!!!! CAUTION: THIS DOES NOT WORK !!!!!!!!!! //
// !!!!!!!!!! CAUTION: THIS DOES NOT WORK !!!!!!!!!! //
}
];
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
perform lazyLoad( routesPath: string ) : LoadChildrenCallback {
return perform() {
return( import( routesPath ).then( m => m.ROUTES ) );
};
}
To me, this code feels much more readable. And, it even compiles! Nevertheless, sadly, it would not work. While you attempt to navigate to the /admin
route, you may see this error within the developer console:
ERROR Error: Uncaught (in promise):
Error: Can’t discover module ‘./admin-view/admin-view.routes’
The rationale for this, as finest I perceive it, is that Angular is utilizing Webpack beneath the hood for all of the bundling and code-splitting. And, in line with this GitHub concern, Webpack performs a static evaluation of import()
statements at construct time in an effort to bundle and split-up the code. As such, it can not work with dynamic paths which might be evaluated at run time (similar to we have now in our earlier code snippet).
Ultimately, I am going to nearly definitely use the Fats-arrow syntax ultimately when defining my lazy-loaded routes in Angular 14 as a result of it reduces a number of the noise with out making it too magical. Nevertheless, it needs to be clear to Angular builders that this can be a stylistic selection solely and has nothing to do with how the Angular code operates.
Need to use code from this publish?
Try the license.