Skip to content

Instantly share code, notes, and snippets.

@daveriedstra
Last active January 13, 2017 23:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daveriedstra/145519e3919795ba8c6438ba4df2a812 to your computer and use it in GitHub Desktop.
Save daveriedstra/145519e3919795ba8c6438ba4df2a812 to your computer and use it in GitHub Desktop.
A way to guess and load modules before bootstrapping angular
/**
This module exports one function, loadModules, which guesses then downloads the modules
which need to be loaded before bootstrapping the application. loadModules() returns an
array of Promises which can be waited on using Promise.all.
The guessing process can handle
- normal loader as route.loadChildren
- redirect as route.redirectTo
- nested lazy loaders using route.data.alsoLoad*
- one level of route params (using a super-simple test)
*route.data.alsoLoad is the path of a Route which hosts the nested lazy route.
Eg, if lazyRoute1 loads lazyRoute2, lazyRoute2.data.alsoLoad = lazyRoute1.path
Usage:
import { loadModules } from 'loadmodules';
import { routes as rootRoutes } from '...';
import { routes as lowerLevelRoutes } from '...';
const haystack:Route[] = rootRoutes.concat(lowerLevelRoutes);
Promise.all(loadModules(haystack, fallbackRoute)).then(() => {
platform.bootstrapModule(AppModule);
})
**/
import { Route } from '@angular/router';
let haystack:Route[];
/*
* Calls all the loaders and returns an array of their promises
*
* Pass the output of this function to Promise.all to wait for all to resolve
* before bootstrapping the application
*/
export function loadModules(_haystack:Route[], _fallback:Route): Promise<any>[] {
haystack = _haystack;
let loaders = getRouteModuleLoaderByWindowLocation();
let out = [];
// if there are no matches, use the fallback
if (loaders.length < 1) {
out = out.concat( getAppropriateLoaders(_fallback) );
}
// call each loader and put its return value in out.
for (let i in loaders)
out.push(loaders[i]());
return out;
};
/*
* Guesses current route by window.location and returns its module loaders
*/
function getRouteModuleLoaderByWindowLocation(_path?:string): (() => Promise<any>)[] {
let path:string = _path || window.location.pathname; // if passed a path, use it; if not, use window.location
let out:(() => Promise<any>)[] = [];
// normalize path by removing possible slashes
if (path.startsWith("/"))
path = path.substr(1);
if (path.endsWith("/"))
path = path.slice(0, -1);
// check each route
for (let i in haystack) {
// path to check against is route.data.fullPath if present, otherwise just route.path
let checkPath = ("data" in haystack[i] && "fullPath" in haystack[i].data) ? (<any> haystack[i].data).fullPath : haystack[i].path;
// got match!
if (checkPath === path) {
out = out.concat( getAppropriateLoaders(haystack[i]) );
}
// maybe routeparam?
// only check one level (for now)
if (checkPath.indexOf("/:") > 0 && path.indexOf('/') > 0) { // has routeparam
checkPath = checkPath.slice(0, checkPath.lastIndexOf("/:"));
// check if matches without path
if ( checkPath === path.slice(0, path.lastIndexOf("/")) ) {
out = out.concat( getAppropriateLoaders(haystack[i]) );
}
}
}
return out;
}
/*
* Gets an array of appropriate loader functions from a route
*
* Typically a route will have only one loader function, but in the case of nested
* lazy routes, we need to load both levels
*/
function getAppropriateLoaders(_route:Route): Array<() => Promise<any>> {
let out = [];
// single loader
if ("loadChildren" in _route) {
out.push(_route.loadChildren);
}
// if router.data.alsoLoad, dig out that module's loader and add to output
if ("data" in _route && "alsoLoad" in _route.data) {
out = out.concat( getRouteModuleLoaderByWindowLocation((<any> _route.data).alsoLoad) );
}
// if route is a redirect, dig out the loader for the route to which it redirects
if ("redirectTo" in _route) {
out = out.concat( getRouteModuleLoaderByWindowLocation(_route.redirectTo) );
}
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment