Angular Ivy 忽略 entryComponents 设置

Angular Ivy ignoring entryComponents setting

我有一个自定义组件装饰器,用于将 link 组件 "names",以便使用 JSON 对象将 link 组件放入层次结构中。

@MyDecorator('name1')
@Component({
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.scss']
})
export class MyComponent implements OnInit {
  // ... rest of the implementation
}

装饰器所做的是自动将组件注册到 Map 中,类似于以下内容:

{
  "name1": MyComponent
}

我有一个配置,几乎是一个动态路由配置,作为 JSON 对象 外部 存储到应用程序代码。

[
  {
    link: '/myroute',
    component: 'name1'
  }
]

在动态主机组件中,我使用如下代码来实例化规定的组件:

// ... gets the component "name"
const componentName = getConfigForRoute('myroute'); 
// should return MyComponent class, if MyComponent gets included in the app bundle:
const componentType = componentRegistry[componentName];

// componentType is ok with ng serve, and undefined in prod builds!
const cf = this.componentFactoryResolver.resolveComponentFactory(componentType);
// reportOutlet is a ViewContainerRef
this.reportOutlet.createComponent(cf);

当通过 ng serve 在开发模式下 运行 时,一切都按预期工作。
通常情况下,生产构建并不顺利:用 MyDecorator 修饰的组件没有被 ts 代码引用,除了应用程序的 NgModule,所以他们很高兴被热心的编译器丢弃。

我(和其他人一样)过去常常将它们包含在模块的 EntryComponents 数组中,但现在 Ivy 似乎只是忽略了它,所以我没有明显的选择来确保组件不会从构建中删除。


@NgModule({
  declarations: [
    AppComponent,
    MyComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    // ...some other stuff
  ],
  entryComponents: [MyComponent],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

我怎样才能完成我以前用 EntryComponents 做的同样的事情,或者让它再次工作?也就是说,确保包含 MyComponent?理想的解决方案是 包含全局列表:拥有装饰器的全部意义在于我不需要维护另一个组件列表,但我会接受所有可行的替代方案。

谢谢!

好吧,我以一种非常丑陋的方式解决了这个问题。

AFAICT,Ivy 让 tsc 和 Webpack 在 tree shake 期间掉落 类 时发挥它们的魔力(不确定细节,这只是我制作的一般图片)。

因此,为了 "emulate" entryComponents,我们必须在某处包含一个 "usage" 组件。我不想在模块外引用这个组件,所以我用 entryComponents "emulation" 解决了这个问题。 很简单:

@NgModule({
  declarations: [
    AppComponent,
    MyComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    // ...some other stuff
  ],
  entryComponents: [MyComponent],
  providers: [
    {
      provide: '__DEFINITELY_NOT_ENTRY_COMPONENTS__',
      // here I can include a list of components not to be dropped by tree shaking
      useValue: [MyComponent]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

我真的希望有更好的方法。
我认为 EntryComponents 有它的用例份额,就像我的一样。