Last active
January 13, 2017 23:51
-
-
Save daveriedstra/145519e3919795ba8c6438ba4df2a812 to your computer and use it in GitHub Desktop.
A way to guess and load modules before bootstrapping angular
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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