mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 13:32:54 +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