feat(linker): Allow configurable module prefixes and suffixes. (#11049)

This commit is contained in:
Alex Rickabaugh 2016-08-24 16:54:42 -07:00 committed by Victor Berchet
parent bd510ccdbb
commit 8b782818f5
4 changed files with 102 additions and 9 deletions

View File

@ -15,7 +15,7 @@ export {ExpressionChangedAfterItHasBeenCheckedException} from './linker/exceptio
export {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory'; export {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';
export {NgModuleFactoryLoader} from './linker/ng_module_factory_loader'; export {NgModuleFactoryLoader} from './linker/ng_module_factory_loader';
export {QueryList} from './linker/query_list'; export {QueryList} from './linker/query_list';
export {SystemJsNgModuleLoader} from './linker/system_js_ng_module_factory_loader'; export {SystemJsNgModuleLoader, SystemJsNgModuleLoaderConfig} from './linker/system_js_ng_module_factory_loader';
export {TemplateRef} from './linker/template_ref'; export {TemplateRef} from './linker/template_ref';
export {ViewContainerRef} from './linker/view_container_ref'; export {ViewContainerRef} from './linker/view_container_ref';
export {EmbeddedViewRef, ViewRef} from './linker/view_ref'; export {EmbeddedViewRef, ViewRef} from './linker/view_ref';

View File

@ -7,7 +7,7 @@
*/ */
import {Injectable} from '../di'; import {Injectable, Optional} from '../di';
import {Compiler} from './compiler'; import {Compiler} from './compiler';
import {NgModuleFactory} from './ng_module_factory'; import {NgModuleFactory} from './ng_module_factory';
@ -15,16 +15,48 @@ import {NgModuleFactoryLoader} from './ng_module_factory_loader';
const _SEPARATOR = '#'; const _SEPARATOR = '#';
const FACTORY_MODULE_SUFFIX = '.ngfactory';
const FACTORY_CLASS_SUFFIX = 'NgFactory'; const FACTORY_CLASS_SUFFIX = 'NgFactory';
/**
* Configuration for SystemJsNgModuleLoader.
* token.
*
* @experimental
*/
export abstract class SystemJsNgModuleLoaderConfig {
/**
* 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: SystemJsNgModuleLoaderConfig = {
factoryPathPrefix: '',
factoryPathSuffix: '.ngfactory',
};
/** /**
* NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory * NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
* @experimental * @experimental
*/ */
@Injectable() @Injectable()
export class SystemJsNgModuleLoader implements NgModuleFactoryLoader { export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
constructor(private _compiler: Compiler) {} private _config: SystemJsNgModuleLoaderConfig;
/**
* @internal
*/
_system: any;
constructor(private _compiler: Compiler, @Optional() config?: SystemJsNgModuleLoaderConfig) {
this._system = () => System;
this._config = config || DEFAULT_CONFIG;
}
load(path: string): Promise<NgModuleFactory<any>> { load(path: string): Promise<NgModuleFactory<any>> {
const offlineMode = this._compiler instanceof Compiler; const offlineMode = this._compiler instanceof Compiler;
@ -35,7 +67,8 @@ export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
let [module, exportName] = path.split(_SEPARATOR); let [module, exportName] = path.split(_SEPARATOR);
if (exportName === undefined) exportName = 'default'; if (exportName === undefined) exportName = 'default';
return System.import(module) return this._system()
.import(module)
.then((module: any) => module[exportName]) .then((module: any) => module[exportName])
.then((type: any) => checkNotEmpty(type, module, exportName)) .then((type: any) => checkNotEmpty(type, module, exportName))
.then((type: any) => this._compiler.compileModuleAsync(type)); .then((type: any) => this._compiler.compileModuleAsync(type));
@ -43,10 +76,15 @@ export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
private loadFactory(path: string): Promise<NgModuleFactory<any>> { private loadFactory(path: string): Promise<NgModuleFactory<any>> {
let [module, exportName] = path.split(_SEPARATOR); let [module, exportName] = path.split(_SEPARATOR);
if (exportName === undefined) exportName = 'default'; let factoryClassSuffix = FACTORY_CLASS_SUFFIX;
if (exportName === undefined) {
exportName = 'default';
factoryClassSuffix = '';
}
return System.import(module + FACTORY_MODULE_SUFFIX) return this._system()
.then((module: any) => module[exportName + FACTORY_CLASS_SUFFIX]) .import(this._config.factoryPathPrefix + module + this._config.factoryPathSuffix)
.then((module: any) => module[exportName + factoryClassSuffix])
.then((factory: any) => checkNotEmpty(factory, module, exportName)); .then((factory: any) => checkNotEmpty(factory, module, exportName));
} }
} }

View File

@ -0,0 +1,49 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Compiler, SystemJsNgModuleLoader} from '@angular/core';
import {async, tick} from '@angular/core/testing';
import {beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
function mockSystem(module: string, contents: any) {
return {
'import': (target: string) => {
expect(target).toBe(module);
return Promise.resolve(contents);
}
};
}
export function main() {
describe('SystemJsNgModuleLoader', () => {
it('loads a default factory by appending the factory suffix', async(() => {
let loader = new SystemJsNgModuleLoader(new Compiler());
loader._system = () => mockSystem('test.ngfactory', {'default': 'test module factory'});
loader.load('test').then(contents => { expect(contents).toBe('test module factory'); });
}));
it('loads a named factory by appending the factory suffix', async(() => {
let loader = new SystemJsNgModuleLoader(new Compiler());
loader._system = () =>
mockSystem('test.ngfactory', {'NamedNgFactory': 'test module factory'});
loader.load('test#Named').then(contents => {
expect(contents).toBe('test module factory');
});
}));
it('loads a named factory with a configured prefix and suffix', async(() => {
let loader = new SystemJsNgModuleLoader(new Compiler(), {
factoryPathPrefix: 'prefixed/',
factoryPathSuffix: '/suffixed',
});
loader._system = () =>
mockSystem('prefixed/test/suffixed', {'NamedNgFactory': 'test module factory'});
loader.load('test#Named').then(contents => {
expect(contents).toBe('test module factory');
});
}));
});
};

View File

@ -1158,10 +1158,16 @@ export declare function style(tokens: string | {
/** @experimental */ /** @experimental */
export declare class SystemJsNgModuleLoader implements NgModuleFactoryLoader { export declare class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
constructor(_compiler: Compiler); constructor(_compiler: Compiler, config?: SystemJsNgModuleLoaderConfig);
load(path: string): Promise<NgModuleFactory<any>>; load(path: string): Promise<NgModuleFactory<any>>;
} }
/** @experimental */
export declare abstract class SystemJsNgModuleLoaderConfig {
factoryPathPrefix: string;
factoryPathSuffix: string;
}
/** @stable */ /** @stable */
export declare abstract class TemplateRef<C> { export declare abstract class TemplateRef<C> {
elementRef: ElementRef; elementRef: ElementRef;