mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00
feat(util): system.js ng-module loader
system.js ng-module loader
This commit is contained in:
49
src/util/module-loader.ts
Normal file
49
src/util/module-loader.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { ComponentFactoryResolver, Injectable, Injector, OpaqueToken, Type } from '@angular/core';
|
||||||
|
import { NgModuleLoader } from './ng-module-loader';
|
||||||
|
|
||||||
|
export const LAZY_LOADED_TOKEN = new OpaqueToken('LZYCMP');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class ModuleLoader {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _ngModuleLoader: NgModuleLoader,
|
||||||
|
private _injector: Injector) {}
|
||||||
|
|
||||||
|
|
||||||
|
load(modulePath: string): Promise<LoadedModule> {
|
||||||
|
console.time(`ModuleLoader, load: ${modulePath}'`);
|
||||||
|
|
||||||
|
const splitString = modulePath.split(SPLITTER);
|
||||||
|
|
||||||
|
return this._ngModuleLoader.load(splitString[0], splitString[1])
|
||||||
|
.then(loadedModule => {
|
||||||
|
console.timeEnd(`ModuleLoader, load: ${modulePath}'`);
|
||||||
|
const ref = loadedModule.create(this._injector);
|
||||||
|
|
||||||
|
return {
|
||||||
|
componentFactoryResolver: ref.componentFactoryResolver,
|
||||||
|
component: ref.injector.get(LAZY_LOADED_TOKEN)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SPLITTER = '#';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
export function provideModuleLoader(ngModuleLoader: NgModuleLoader, injector: Injector) {
|
||||||
|
return new ModuleLoader(ngModuleLoader, injector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface LoadedModule {
|
||||||
|
componentFactoryResolver: ComponentFactoryResolver;
|
||||||
|
component: Type<any>;
|
||||||
|
};
|
77
src/util/ng-module-loader.ts
Normal file
77
src/util/ng-module-loader.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { Compiler, Injectable, NgModuleFactory, Optional } from '@angular/core';
|
||||||
|
|
||||||
|
const FACTORY_CLASS_SUFFIX = 'NgFactory';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for NgModuleLoader.
|
||||||
|
* token.
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
export abstract class NgModuleLoaderConfig {
|
||||||
|
/**
|
||||||
|
* Prefix to add when computing the name of the factory module for a given module name.
|
||||||
|
*/
|
||||||
|
factoryPathPrefix: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suffix to add when computing the name of the factory module for a given module name.
|
||||||
|
*/
|
||||||
|
factoryPathSuffix: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG: NgModuleLoaderConfig = {
|
||||||
|
factoryPathPrefix: '',
|
||||||
|
factoryPathSuffix: '.ngfactory',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class NgModuleLoader {
|
||||||
|
private _config: NgModuleLoaderConfig;
|
||||||
|
|
||||||
|
constructor(private _compiler: Compiler, @Optional() config?: NgModuleLoaderConfig) {
|
||||||
|
this._config = config || DEFAULT_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
load(modulePath: string, ngModuleExport: string) {
|
||||||
|
const offlineMode = this._compiler instanceof Compiler;
|
||||||
|
return offlineMode ? loadPrecompiledFactory(this._config, modulePath, ngModuleExport) : loadAndCompile(this._compiler, modulePath, ngModuleExport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function loadAndCompile(compiler: Compiler, modulePath: string, ngModuleExport: string): Promise<NgModuleFactory<any>> {
|
||||||
|
if (!ngModuleExport) {
|
||||||
|
ngModuleExport = 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.import(modulePath)
|
||||||
|
.then((rawModule: any) => {
|
||||||
|
const module = rawModule[ngModuleExport];
|
||||||
|
if (!module) {
|
||||||
|
throw new Error(`Module ${modulePath} does not export ${ngModuleExport}`);
|
||||||
|
}
|
||||||
|
return compiler.compileModuleAsync(module);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function loadPrecompiledFactory(config: NgModuleLoaderConfig, modulePath: string, ngModuleExport: string): Promise<NgModuleFactory<any>> {
|
||||||
|
let factoryClassSuffix = FACTORY_CLASS_SUFFIX;
|
||||||
|
if (ngModuleExport === undefined) {
|
||||||
|
ngModuleExport = 'default';
|
||||||
|
factoryClassSuffix = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.import(config.factoryPathPrefix + modulePath + config.factoryPathSuffix)
|
||||||
|
.then((rawModule: any) => {
|
||||||
|
const ngModuleFactory = rawModule[ngModuleExport + factoryClassSuffix];
|
||||||
|
if (!ngModuleFactory) {
|
||||||
|
throw new Error(`Module ${modulePath} does not export ${ngModuleExport}`);
|
||||||
|
}
|
||||||
|
return ngModuleFactory;
|
||||||
|
});
|
||||||
|
}
|
Reference in New Issue
Block a user