Skip to content

Commit a0688ae

Browse files
dtabuencchristopherthielen
authored andcommitted
feat(ng2.lazyLoad): Support passing callback to lazyLoad for loading ng2 module (angular-ui#3037)
This enables dealing with the loading of modules with a custom callback thus skipping the default NgModuleLoader. This is a must-have in order to enable lazy-loading using webpack.
1 parent d43c1fd commit a0688ae

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

src/ng2/lazyLoadNgModule.ts

+34-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** @module ng2 */ /** */
2-
import {NgModuleFactoryLoader, NgModuleRef, Injector, NgModuleFactory} from "@angular/core";
2+
import {NgModuleFactoryLoader, NgModuleRef, Injector, NgModuleFactory, Type, Compiler} from "@angular/core";
33

44
import {LazyLoadResult} from "../state/interface";
55

@@ -10,6 +10,8 @@ import {UIRouter} from "../router";
1010
import {Resolvable} from "../resolve/resolvable";
1111
import {NATIVE_INJECTOR_TOKEN} from "../resolve/resolveContext";
1212

13+
export type ModuleTypeCallback = () => Type<any> | Promise<Type<any>>;
14+
1315
/**
1416
* Returns a function which lazy loads a nested module
1517
*
@@ -24,23 +26,47 @@ import {NATIVE_INJECTOR_TOKEN} from "../resolve/resolveContext";
2426
*
2527
* returns the new states array
2628
*/
27-
export function loadNgModule(path: string): (transition: Transition) => Promise<LazyLoadResult> {
29+
export function loadNgModule( moduleToLoad: string | ModuleTypeCallback): (transition: Transition) => Promise<LazyLoadResult> {
2830
/** Get the parent NgModule Injector (from resolves) */
2931
const getNg2Injector = (transition: Transition) =>
3032
transition.injector().getAsync(NATIVE_INJECTOR_TOKEN);
3133

34+
/**
35+
* Returns the module factory that can be used to instantiate a module
36+
*
37+
* For strings this:
38+
* - Finds the correct NgModuleFactoryLoader
39+
* - Loads the new NgModuleFactory from the path string (async)
40+
*
41+
* For a Type<any> or Promise<Type<any>> this:
42+
* - Compiles the component type (if not running with AOT)
43+
* - Returns the NgModuleFactory resulting from compilation (or direct loading if using AOT) as a Promise
44+
*
45+
*/
46+
const loadModuleFactory = (loadChildren: string | ModuleTypeCallback, ng2Injector: Injector): Promise<NgModuleFactory<any>>=>{
47+
if(typeof(loadChildren) === 'string'){
48+
return ng2Injector.get(NgModuleFactoryLoader).load(loadChildren);
49+
}
50+
else{
51+
const compiler: Compiler = ng2Injector.get(Compiler);
52+
const offlineMode = compiler instanceof Compiler;
53+
const loadChildrenPromise = Promise.resolve(loadChildren());
54+
return offlineMode ? loadChildrenPromise : loadChildrenPromise.then( moduleType => compiler.compileModuleAsync(moduleType))
55+
}
56+
}
57+
3258
/**
3359
* Lazy loads the NgModule using the NgModuleFactoryLoader
3460
*
3561
* Use the parent NgModule's Injector to:
36-
* - Find the correct NgModuleFactoryLoader
37-
* - Load the new NgModuleFactory from the path string (async)
62+
* - Find the correct NgModuleFactory
3863
* - Create the new NgModule
3964
*/
40-
const createNg2Module = (path: string, ng2Injector: Injector) =>
41-
ng2Injector.get(NgModuleFactoryLoader).load(path).then((factory: NgModuleFactory<any>) =>
65+
const createNg2Module = ( moduleToLoad: string | ModuleTypeCallback , ng2Injector: Injector) =>
66+
loadModuleFactory(moduleToLoad, ng2Injector).then((factory: NgModuleFactory<any>) =>
4267
factory.create(ng2Injector));
4368

69+
4470
/**
4571
* Apply the UI-Router Modules found in the lazy loaded module.
4672
*
@@ -75,7 +101,7 @@ export function loadNgModule(path: string): (transition: Transition) => Promise<
75101

76102
let replacementState = uiRouter.stateRegistry.get(originalName);
77103
if (replacementState === originalState) {
78-
throw new Error(`The module that was loaded from ${path} should have a ui-router state named '${originalName}'`);
104+
throw new Error(`The module that was loaded from ${moduleToLoad} should have a ui-router state named '${originalName}'`);
79105
}
80106

81107
// Supply the newly loaded states with the Injector from the lazy loaded NgModule
@@ -85,6 +111,6 @@ export function loadNgModule(path: string): (transition: Transition) => Promise<
85111
}
86112

87113
return (transition: Transition) => getNg2Injector(transition)
88-
.then((injector: Injector) => createNg2Module(path, injector))
114+
.then((injector: Injector) => createNg2Module(moduleToLoad, injector))
89115
.then((moduleRef: NgModuleRef<any>) => loadUIRouterModules(transition, moduleRef))
90116
}

0 commit comments

Comments
 (0)