【问题标题】:In Angular, if I import a shared module but only need 1 thing from it, won't that be a unnecessarily huge import?在 Angular 中,如果我导入一个共享模块但只需要其中的一件事,那会不会是一个不必要的巨大导入?
【发布时间】:2018-10-01 11:43:51
【问题描述】:

假设我有一个 SharedModule,它导入了一堆服务、管道等,然后在 FeatureModuleA 我想使用一个在 SharedModule 中声明的管道.

然后我正在导入 SharedModule,它可能包含 100 个不同的管道,但其中 99 个在 FeatureModuleA 中成为未使用和死代码。这不是很没有效率吗?

这让我想到了 tree shaking,其中 webpack 可能会删除未使用的代码,但 AFAIK,tree shaking 会删除已导出但尚未导入的代码。在我的情况下,所有内容都是由 SharedModule 导入的,那么这到底是如何工作的呢?我会因为需要 1/100 个管道而有 99% 未使用的代码吗?

有人愿意解释一下吗?在官方文档中找不到任何信息。

【问题讨论】:

  • 共享模块是否存在于您的 AppModule 中?
  • 不,我以为我只在那些需要 SharedModule 的功能模块中导入 SharedModule。
  • 如果你的sharedmodule已经被AppModule导入了,你可以在providers中提到管道。这样你就可以在组件的任何地方访问它
  • 您还可以将私有模块添加到您的componentA,然后在其中添加您需要的一些管道/服务

标签: angular


【解决方案1】:

如果您的应用程序正在增长并且您需要导入特定的服务/管道/模型。您可以尝试在您创建的每个模块中实现一个索引桶

例如,这是您的 /shared 目录结构。考虑创建一个 index.ts 导出 /shared 目录下的所有文件。

 /shared
      /services
          user.service.ts
          tenant.service.ts
      /pipes
          table.pipe.ts
      /models
          admin.model.ts
          product.model.ts
 index.ts                       --> Your index.ts
 shared.module.ts

创建 index.ts 后,提供共享目录下的所有导出:

export * from './services/user.service';
export * from './services/tenant.service';

export * from './table.pipe';

export * from './models/admin.model';
export * from './product.model';

您也可以在将其导入共享模块时使用它,以避免导入长列表并促进单行导入样式

例子: 从 './index.ts' 导入 { UserService, TenantService, TablePipe, Admin, Product }

因此,当您只想将一个 1 服务/管道/模型导入到您的其他模块示例 UserModule 时,只需调用 索引桶

import { UserService } from '../shared/index';

// or if you want to import 2 items e.g a service and a pipe
import { UserService, TablePipe } from '../shared/index';


@NgModule({
   declarations: [`...`],
   imports: [`...`],
   providers: [ UserService ]    --> imported from /shared index barrel
})
export class UserModule {}

这样,每当您的应用程序增长时,作为共享模块,您就可以通过索引桶一个一个或两个或多个项目的组合调用它们

【讨论】:

  • 有趣。但是这种桶文件方法不是让 SharedModule 过时了吗?为什么不在我的所有模块中以这种方式导入?很少有一个功能模块需要在 SharedModule 中声明的所有内容...
  • 不,SharedModule 不会过时,因为桶只是为了将您的导入缩短为一行声明,然后您自己的共享模块和其他模块将使用该声明。因此,在您的情况下,如果您只想要 /shared 目录中的 TablePipe - 无需导入 SharedModule 而是仅导入 TablePipe 可以轻松访问“import { TablePipe } from './shared/index'”,而不是提供完整的然后将目录地址包含在您选择的模块中。
  • 这也是一个很好的阅读来自 Medium Site 的资源 - 它还讨论了共享和功能模块 - 希望这也会有所帮助:medium.com/@tomastrajan/…
  • 嗨@RogérioOliveira,如果我做对了,我不知道,但是在共享模块中将使用充满导出的index.ts来在一行中导入所有必需的文件,就像角度一样实施了它的进口。 SharedModule 是一个需要在其他模块中导入的模块,以共享那些以后可以使用的共享导入。希望这能回答你的问题:)
  • 谢谢@KShewengger,我最近开始使用 Angular,所以不要介意我的无知......我在我的 Vue 和 React 应用程序中经常使用这个概念(很棒)。实际上,我正在研究有关 Angular 模块的所有概念。特别是关于共享模块,我试图找到某种方法将其分解为“本地共享模块”而不是全局模块。我的应用程序有一些模块仅由几个模块导入。这样,我不想将这些人放在我的全局共享模块中,而是有一个本地共享模块,我可以在其中只导入和导出这些特定模块。非常感谢。
【解决方案2】:

导入诸如SharedModule 之类的完整模块效率低下,因为它还包含其他组件。

如果您也打算在其他地方使用这些管道,您可以做的是创建一个包含所有管道的通用模块(甚至可能在 SharedModule 内)。在这种情况下,您只会导入必要的管道。

如果您打算大量扩展应用程序,这甚至可以帮助您避免循环依赖。

【讨论】:

    【解决方案3】:

    我会回答这个问题,因为从我在文档上阅读的内容来看,答案没有考虑到 Angular 只评估第一次导入的模块,例如,拥有一个 sharedModule.ts 与所有共享模块, 是一种很好的做法,并不意味着您的捆绑包会更大。

    来自docs

    如果我两次导入同一个模块会怎样?

    这不是问题。什么时候 三个模块都导入模块'A',Angular评估模块'A' 一次,它第一次遇到它,以后就不会再遇到了。

    无论 A 级别出现在导入的层次结构中,这都是正确的 Ng 模块。当模块'B'导入模块'A'时,模块'C'导入'B', 和模块'D'导入[C,B,A],然后'D'触发评估 'C',触发评估'B',评估'A'。什么时候 Angular 到达 'D' 中的 'B' 和 'A',它们已经被缓存并且 准备好了。

    Angular 不喜欢带有循环引用的 NgModules,所以不要让 模块“A”导入模块“B”,它导入模块“A”。

    以下是共享模块的 DOES 和 DONTS:(Read the article)

    • 请声明组件、管道、指令并导出它们。
    • 请务必导入 FormsModule、ReactiveFormsModule 和其他(第 3 方)模块 需要。
    • 务必将 SharedModule 导入任何其他功能模块。
    • 不要在 SharedModule 中提供应用范围的单例服务。而是将它们移至 CoreModule。
    • 请勿将 SharedModule 导入 AppModule。

    【讨论】:

      猜你喜欢
      • 2022-12-10
      • 1970-01-01
      • 2018-01-16
      • 2018-08-25
      • 2018-03-29
      • 1970-01-01
      • 2023-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多