angular - 在 Angular 应用程序中动态包含另一个 webpack 包

标签 angular webpack bundle require

我正在开发一个与 webpack bundle 在一起的 Angular2 应用程序。一切正常。然而,这个 bundle 的应用程序将在运行时独立交付,在引导应用程序之前,我需要将其他 NgModules 指定到我 bundle 在我的应用程序中的模块之一。基本上可以将其视为包含在 index.html 中的两个包,当引导时,包 1 进入包 2。只有 bundle 2 引导应用程序。所以我做了一些实验,想与大家分享,以阐明这一点(我可能采取了一种相当肮脏且完全错误的方法,所以如果是这样,请纠正。如果它是肮脏的,我不介意是它可以工作的唯一方法。)。唯一的要求是在转译过程中什么都不应该做。要求是我可以在我的 index.html 中包含一个或多个包,并且它们可以在彼此事先不了解的情况下连接到实际的应用程序中。

我首先这样做的原因是因为我在一个平台上工作,其他开发人员可以通过安装扩展来挂接代码。这意味着我交付了初始包,它对其他包的转译时间一无所知。这在 AngularJS 中很容易,但移动到 Angular2 及更高版本时,就不再那么容易了。

我设法通过以下方法延迟引导应用程序:

在 main.ts 中:

window["platformBrowserDynamicRef"] = platformBrowserDynamic();
window["appModule"] = AppModule;

这工作正常,当我手动调用 bootstrap 时,应用程序启动正常。 我创建了另一个 bundle ,它可以作为另一个应用程序独立运行。

当我尝试通过像上面那样在隐式数组中导入组件来将它们 bundle 在一起,并引导应用程序时,我收到一个错误,我不知道该怎么做。

window["app"].modulesImport.push(CommonModule);
window["app"].modulesImport.push(FormsModule);
window["app"].modulesImport.push(BrowserModule);
window["app"].modulesImport.push(NgGridModule);
window["app"].modulesImport.push(ReactiveFormsModule);
window["app"].modulesImport.push(BrowserAnimationsModule);
window["app"].modulesImport.push(HttpModule);

@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
        };
    }
}

将模块放在隐式数组中工作正常,但是一旦我从其他包中添加模块,我就会收到以下错误:

Uncaught 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>]

我还尝试过 AoT 编译 ExtensionsModule,但它也不起作用。 我还尝试使用 JitCompiler 在运行时动态编译组件,看看我是否可以通过这种方式将它们添加到应用程序中。但是同样的错误。

在应用程序的引导过程中或在转译过程中是否对组件进行了修饰? 查看我的隐式数组中的模块,我可以看到它们经过装饰,但我的没有。那个webpack是不是插入了装饰器方法的调用代码?我假设装饰器信息在转译过程中丢失了,所以也许我需要以某种方式临时存储它,以便我可以在其他地方获取它。 (注意作为第一个元素的 extensionsmodule 不包含装饰器数组)

modules that should be imported in my module

我想我正在寻找有关如何从这里继续前进的指示。也许 NgModule 注释功能是一个很好的起点。虽然无法在任何地方找到它。

编辑

深入研究这个问题我尝试了使用路由器的延迟加载方法,首先我遇到了这个错误,试图用 js 文件加载它(网络选项卡显示它从不发出文件请求):

const appRoutes: Routes = [
      {
        path: 'edit-entity/:type/:id/:culture',
        component: EntityEditor,
        resolve: {
            entity: EntityResolver,
            navigation: NavigationResolver
        },
        data: { shouldDetach: true},
        loadChildren: "/dist/extensions.bundle.js#ExtensionsBundle",

      },
      {
        path: '',
        component: Dashboard,
        resolve: {
            navigation: NavigationResolver
        },
        data: { shouldDetach: true}        
      }
    ];

解决了以下错误: “找不到名为 ExtensionsModule.js 的模块”

其次,我尝试使用这样的 loadChildren 函数:

const appRoutes: Routes = [
      {
        path: 'edit-entity/:type/:id/:culture',
        component: EntityEditor,
        resolve: {
            entity: EntityResolver,
            navigation: NavigationResolver
        },
        data: { shouldDetach: true},
        loadChildren: () => {
            //"/dist/extensions.bundle.js#ExtensionsModule",            
            // return System.import('./dynamic.module').then((comp: any) => {
            //     return comp.otherExport;
            // });

            return window["lux"].modulesLazyImport[0];
        }
      },
      {
        path: '',
        component: Dashboard,
        resolve: {
            navigation: NavigationResolver
        },
        data: { shouldDetach: true}        
      }
    ];

解决于:

app.bundle.js:1548 ERROR Error: Uncaught (in promise): Error: No NgModule metadata found for 'ExtensionsModule'.
Error: No NgModule metadata found for 'ExtensionsModule'.
    at NgModuleResolver.resolve (app.bundle.js:55709) [angular]
    at CompileMetadataResolver.getNgModuleMetadata (app.bundle.js:56288) [angular]
    at JitCompiler._loadModules (app.bundle.js:67404) [angular]
    at JitCompiler._compileModuleAndComponents (app.bundle.js:67363) [angular]
    at JitCompiler.compileModuleAsync (app.bundle.js:67325) [angular]
    at ModuleBoundCompiler.compileModuleAsync (app.bundle.js:67693) [angular]
    at MergeMapSubscriber.project (app.bundle.js:30608) [angular]
    at MergeMapSubscriber._tryNext (app.bundle.js:69744) [angular]
    at MergeMapSubscriber._next (app.bundle.js:69734) [angular]
    at MergeMapSubscriber.Subscriber.next (app.bundle.js:14584) [angular]
    at ScalarObservable._subscribe (app.bundle.js:69206) [angular]
    at ScalarObservable.Observable.subscribe (app.bundle.js:118) [angular]
    at MergeMapOperator.call (app.bundle.js:69709) [angular]
    at Observable.subscribe (app.bundle.js:115) [angular]
    at NgModuleResolver.resolve (app.bundle.js:55709) [angular]
    at CompileMetadataResolver.getNgModuleMetadata (app.bundle.js:56288) [angular]
    at JitCompiler._loadModules (app.bundle.js:67404) [angular]
    at JitCompiler._compileModuleAndComponents (app.bundle.js:67363) [angular]
    at JitCompiler.compileModuleAsync (app.bundle.js:67325) [angular]
    at ModuleBoundCompiler.compileModuleAsync (app.bundle.js:67693) [angular]
    at MergeMapSubscriber.project (app.bundle.js:30608) [angular]
    at MergeMapSubscriber._tryNext (app.bundle.js:69744) [angular]
    at MergeMapSubscriber._next (app.bundle.js:69734) [angular]
    at MergeMapSubscriber.Subscriber.next (app.bundle.js:14584) [angular]
    at ScalarObservable._subscribe (app.bundle.js:69206) [angular]
    at ScalarObservable.Observable.subscribe (app.bundle.js:118) [angular]
    at MergeMapOperator.call (app.bundle.js:69709) [angular]
    at Observable.subscribe (app.bundle.js:115) [angular]
    at resolvePromise (app.bundle.js:77503) [angular]
    at resolvePromise (app.bundle.js:77488) [angular]
    at :3000/dist/app.bundle.js:77537:17 [angular]
    at Object.onInvokeTask (app.bundle.js:4599) [angular]
    at ZoneDelegate.invokeTask (app.bundle.js:77289) [angular]
    at Zone.runTask (app.bundle.js:77179) [<root> => angular]
    at drainMicroTaskQueue (app.bundle.js:77433) [<root>]
    at HTMLDivElement.ZoneTask.invoke (app.bundle.js:77364) [<root>]

编辑 我认为错误可能是因为我的注释从未被调用过。不确定是否是这种情况。我决定在其上使用 ES5 并将组件推送到我的隐式列表,如下所示。尝试将组件推送到 parts.module.ts 的声明部分时,毕竟会出现相同的错误。

    var HelloWorldComponent = function () {

};

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

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

那么这是 Angular 4.0.0 中的一个错误还是根本不可能创建一个插件机制?

最好的问候 莫腾

最佳答案

我能找到的实现这一目标的唯一方法是放弃 webpack,因为它似乎在构建时需要所有信息,并使用 SystemJS,它在运行时可以加载它不知道的模块

关于angular - 在 Angular 应用程序中动态包含另一个 webpack 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43203490/

相关文章:

javascript - 获取 'base' url Angular 5

reactjs - webpack react 应用程序中的 NODE_ENV 设置不正确

iphone - iPhone 应用程序的“设置”包中嵌套多值说明符

ios - Bundle 无效 Xcode 发布错误

java - OSGi/BND : How to exclude classes from bundle generation?

angular - 在 ngx-datatable 中显示带有列名的图标

javascript - 使用 s3 getobjectcommand 结果以 Angular (以 pdf 形式打开)

unit-testing - 测试使用全局事件总线的 Vue 单文件组件

angular - "You seem to not be depending on "@ Angular/核心 "."

javascript - Webpack:Bundle.js - 未捕获的 ReferenceError:未定义进程