теперь можно использовать исполняющий компилятор в Angular для загрузки модулей, которые были упакованы с веб-пакетом, используя webpack-system-register

я есть угловое приложение, созданное с использованием Typescript и связанное с веб-пакетом. Здесь нет ничего необычного. То, что я хочу сделать, это разрешить плагины во время выполнения, что означает, что компоненты и / или модули за пределами пакета также должны иметь возможность регистрироваться в приложении. До сих пор я пытался включить другой пакет веб-пакета в index.html и использовать массив Implict, чтобы вставить в него упомянутый модуль / компонент, и импортировать их в мой модуль.

Посмотрите, что импорт использует переменную Implict. Это работает для модулей внутри пакета, но модули из другого пакета не будут работать.

@NgModule({
  imports: window["app"].modulesImport,
  declarations: [
      DYNAMIC_DIRECTIVES,
      PropertyFilterPipe,
      PropertyDataTypeFilterPipe,
      LanguageFilterPipe,      
      PropertyNameBlackListPipe      
  ],
  exports: [
      DYNAMIC_DIRECTIVES,
      CommonModule,
      FormsModule,
      HttpModule
  ]
})
export class PartsModule {

    static forRoot()
    {
        return {
            ngModule: PartsModule,
            providers: [ ], // not used here, but if singleton needed
        };
    }
}

Я также попытался создать модуль и компонент с использованием кода es5, как показано ниже, и вставить то же самое в мой массив модулей:

var HelloWorldComponent = function () {

};

HelloWorldComponent.annotations = [
    new ng.core.Component({
        selector: 'hello-world',
        template: '<h1>Hello World!</h1>',
    })
];

window["app"].componentsLazyImport.push(HelloWorldComponent);

Оба подхода приводят к следующей ошибке:

ncaught Error: Unexpected value 'ExtensionsModule' imported by the module 'PartsModule'. Please add a @NgModule annotation.
    at syntaxError (http://localhost:3002/dist/app.bundle.js:43864:34) [<root>]
    at http://localhost:3002/dist/app.bundle.js:56319:44 [<root>]
    at Array.forEach (native) [<root>]
    at CompileMetadataResolver.getNgModuleMetadata (http://localhost:3002/dist/app.bundle.js:56302:49) [<root>]
    at CompileMetadataResolver.getNgModuleSummary (http://localhost:3002/dist/app.bundle.js:56244:52) [<root>]
    at http://localhost:3002/dist/app.bundle.js:56317:72 [<root>]
    at Array.forEach (native) [<root>]
    at CompileMetadataResolver.getNgModuleMetadata (http://localhost:3002/dist/app.bundle.js:56302:49) [<root>]
    at CompileMetadataResolver.getNgModuleSummary (http://localhost:3002/dist/app.bundle.js:56244:52) [<root>]
    at http://localhost:3002/dist/app.bundle.js:56317:72 [<root>]
    at Array.forEach (native) [<root>]
    at CompileMetadataResolver.getNgModuleMetadata (http://localhost:3002/dist/app.bundle.js:56302:49) [<root>]
    at JitCompiler._loadModules (http://localhost:3002/dist/app.bundle.js:67404:64) [<root>]
    at JitCompiler._compileModuleAndComponents (http://localhost:3002/dist/app.bundle.js:67363:52) [<root>]

Обратите внимание, что если я пытаюсь использовать компонент вместо модуля, я вместо этого помещаю их в объявления, что приводит к соответствующей ошибке для компонентов, говорящих о необходимости добавить аннотацию @ pipe / @ component.

Я чувствую, что это должно быть выполнимо, но я не знаю, чего мне не хватает. Я использую [email protected]

обновление 05.11.2017

Поэтому я решил сделать шаг назад и начать все с нуля. Вместо того, чтобы использоватьWebPack Я решил попробовать сSystemJS вместо этого, как я нашел основной компонент в Angular. На этот раз я работал, используя следующие компоненты и службы для вставки компонентов:

typebuilder.ts

import { Component, ComponentFactory, NgModule, Input, Injectable, CompilerFactory } from '@angular/core';
import { JitCompiler } from '@angular/compiler';
import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";

export interface IHaveDynamicData { 
    model: any;
}

@Injectable()
export class DynamicTypeBuilder {

    protected _compiler : any;
         // wee need Dynamic component builder
    constructor() {
        const compilerFactory : CompilerFactory = platformBrowserDynamic().injector.get(CompilerFactory);
        this._compiler = compilerFactory.createCompiler([]);
    }

  // this object is singleton - so we can use this as a cache
    private _cacheOfFactories: {[templateKey: string]: ComponentFactory<IHaveDynamicData>} = {};

    public createComponentFactoryFromType(type: any) : Promise<ComponentFactory<any>> {
        let module = this.createComponentModule(type);
            return new Promise((resolve) => {
            this._compiler
                .compileModuleAndAllComponentsAsync(module)
                .then((moduleWithFactories : any) =>
                {
                    let _ = window["_"];
                    let factory = _.find(moduleWithFactories.componentFactories, { componentType: type });
                    resolve(factory);
                });
        });
    }

    protected createComponentModule (componentType: any) {
        @NgModule({
        imports: [
        ],
        declarations: [
            componentType
        ],
        })
        class RuntimeComponentModule
        {
        }
        // a module for just this Type
        return RuntimeComponentModule;
    }
}

Dynamic.component.ts

import { Component, Input, ViewChild, ViewContainerRef, SimpleChanges, AfterViewInit, OnChanges, OnDestroy, ComponentFactory, ComponentRef } from "@angular/core";
import { DynamicTypeBuilder } from "../services/type.builder";

@Component({
    "template": '<h1>hello dynamic component <div #dynamicContentPlaceHolder></div></h1>',
    "selector": 'dynamic-component'
})
export class DynamicComponent implements AfterViewInit, OnChanges, OnDestroy {

    @Input() pathToComponentImport : string;

    @ViewChild('dynamicContentPlaceHolder', {read: ViewContainerRef}) 
    protected dynamicComponentTarget: ViewContainerRef;
    protected componentRef: ComponentRef<any>;

    constructor(private typeBuilder: DynamicTypeBuilder) 
    {

    }  

    protected refreshContent() : void {
        if (this.pathToComponentImport != null && this.pathToComponentImport.indexOf('#') != -1) {
          let [moduleName, exportName] = this.pathToComponentImport.split("#");
          window["System"].import(moduleName)
            .then((module: any) => module[exportName])
            .then((type: any) => {
                this.typeBuilder.createComponentFactoryFromType(type)
                .then((factory: ComponentFactory<any>) =>
                {
                    // Target will instantiate and inject component (we'll keep reference to it)
                    this.componentRef = this
                        .dynamicComponentTarget
                        .createComponent(factory);

                    // let's inject @Inputs to component instance
                    let component = this.componentRef.instance;

                    component.model = { text: 'hello world' };

                    //...
                });
            });
      }
    }

    ngOnDestroy(): void {
    }

    ngOnChanges(changes: SimpleChanges): void {
    }

    ngAfterViewInit(): void {
        this.refreshContent();
    }

}

Теперь я могу ссылаться на любой данный компонент, как это:

<dynamic-component pathToComponentImport="/app/views/components/component1/extremely.dynamic.component.js#ExtremelyDynamicComponent"></dynamic-component>

Конфигурация Typescript:

 {
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "allowJs": true,
    "experimentalDecorators": true,
    "lib": [ "es2015", "dom" ],
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true
  },
    "exclude": [
      "node_modules",
      "systemjs-angular-loader.js",
      "systemjs.config.extras.js",
      "systemjs.config.js"
  ]
}

И выше моего конфига машинописи. Так что это работает, однако я не уверен, что я доволен использованием SystemJS. Я чувствую, что это должно быть возможно и с веб-пакетом, и я не уверен, что именно так TC компилирует файлы, которых не понимает веб-пакет ... Я все еще получаю исключение отсутствующего декоратора, если я пытаюсь запустить этот код в комплекте веб-пакета ,

С наилучшими пожеланиями Мортен

Ответы на вопрос(1)

Ваш ответ на вопрос