【问题标题】:Performance of a shared Angular Material module that may include many Component modules?可能包含许多组件模块的共享 Angular Material 模块的性能?
【发布时间】:2019-08-31 13:06:12
【问题描述】:

Angular Material component usage guide 建议创建一个共享模块以包含多个组件。我的问题是关于共享模块的使用。

共享角度材质模块

import {MatButtonModule} from '@angular/material/button';
import {MatCheckboxModule} from '@angular/material/checkbox';

@NgModule({
  imports: [MatButtonModule, MatCheckboxModule],
  exports: [MatButtonModule, MatCheckboxModule],
})
export class MyOwnCustomMaterialModule { }

这个共享模块可以包含许多组件模块。也许50个或更多。假设我已将此共享模块导入另一个模块,它只需要一个材料模块。在这种情况下,是否存在性能损失,例如加载时间?共享模块是否缓存?

【问题讨论】:

    标签: angular typescript angular-material


    【解决方案1】:

    NgModule FAQs 包含以下注释。

    What if I import the same module twice?

    这不是问题。 当三个模块都导入 Module 'A' 时,Angular 会评估 Module 'A' 一次,这是它第一次遇到它,并且不会再次这样做。

    在导入的 NgModules 层次结构中出现的任何级别 A 都是如此。当模块'B'导入模块'A',模块'C'导入'B',模块'D'导入[C,B,A],然后'D'触发'C'的评估,这触发评估'B',它评估'A'。当 Angular 到达“D”中的“B”和“A”时,它们已经被缓存并准备好了

    Angular 不喜欢带有循环引用的 NgModules,所以不要让 Module 'A' 导入 Module 'B',它会导入 Module 'A'。


    仅包含特定应用程序所需的 Angular Material 组件模块可以带来额外的性能优势。

    deprecation notice for Angular Material beta.3 声明:

    材料模块

    MaterialModule(和MaterialRootModule)已被标记为已弃用。 我们发现,就目前世界上的 tree-shaking 状态而言,使用 MaterialModule 之类的聚合 NgModule 会导致工具无法消除未使用组件的代码。

    为了确保用户最终获得尽可能小的代码大小,我们将弃用 MaterialModule,并将在后续版本中删除。

    要替换 MaterialModule,用户可以在其应用程序中创建自己的“材料”模块(例如,GmailMaterialModule),该模块仅导入应用程序中实际使用的组件集。

    同样的建议在 2019 年仍然适用。Angular Material getting started guide states

    或者,您可以创建一个单独的NgModule 来导入然后重新导出您将在应用程序中使用的所有Angular Material 组件。通过再次导出它们,其他模块可以在任何需要 Material 组件的地方简单地包含您的CustomMaterialModule,并自动获取所有导出的 Material 模块。 SharedModule 是导入/导出应用程序范围的 Material 模块的好地方。

    【讨论】:

    • 您指的是 2017 发行说明。但是我已经放了最新的材料指导文档。那么呢? material.angular.io/guide/getting-started
    • @Sampath 当前的 Angular Material 入门指南仍然建议将组件模块限制为应用程序所需的模块以提高性能。请参阅 NgModule 常见问题解答中有关缓存模块的说明。
    【解决方案2】:

    停止使用共享材质模块

    在测试大多数 Angular 文章推荐的方式的性能之前,我的想法和回答这个问题的人一样,但是像这样 article,我得出以下结论:

    停止使用共享材质模块

    从文章中可以看出,将所有 Angular 模块合并到一个模块中并不是一个好主意。测试结果很简单,就像ABC一样。

    另一个重要的一点是其他答案中提到的链接。比如这个Getting Started with Angular Material,目前不推荐创建导出Angular Material模块的模块。

    【讨论】:

      【解决方案3】:

      不久前我也有同样的问题,我发现这篇文章并将其添加为书签:Avoiding Common Confusions with Modules in Angular,作者为Max Koretskyi aka Wizard

      模块缓存

      开发人员有时会在 stackoverflow 上弹出一个新问题,他担心将模块导入惰性和非惰性模块会导致运行时模块代码重复。这是一个可以理解的假设。但无需担心,因为所有现有的模块加载器都会缓存它们加载的模块

      当 SystemJS 加载一个模块时,它会将其放入缓存中。下次有对该模块的请求时,它会从缓存中返回它,并且不会执行额外的网络请求。这是每个模块都会发生的过程。

      例如,当你编写 Angular 组件时,你会从 Angular/core 模块中导入 Component 装饰器:

      import { Component } from '@angular/core';

      您在应用程序中多次引用包。但是 SystemJS 并不是每次都加载 angular/core 包。它加载一次并缓存它。 如果您使用 angular-cli 或自己配置 webpack,Webpack 也会发生类似的情况。它在包中仅包含一次模块代码并为其提供 ID。所有其他模块都使用此 ID 从该模块导入符号。

      我建议您阅读整篇文章并做一些个人笔记,因为它确实帮助我消除了对 Angular 架构的一些疑问。我认为它写得非常好,而且本身解释清楚,所以我不打算重新发明轮子并解释它。


      无论如何,SharedModule 用于共享组件、管道和指令。尽管您可能正在导入 3rd 方库模块并导出它们以共享它们。本质上,您共享的是在第 3 方库的模块(在本例中为 Angular Material 的模块)中声明的组件、管道和指令。

      SharedModule is compiled into main-abcd1234.js,类似于此帖子编译日志中间的内容:

      main-abcd1234.js 在应用启动时加载。您可以通过查看应用初始加载中的网络选项卡来验证这一点。

      如您所见,对于我当前的项目,它并不是很大,只有几百 KB。您可以测试您的“应用程序大小”是否会增加,方法是将共享模块导入到模块 X 中,该模块仅使用共享模块中的 1 个组件,并检查模块 X 的编译包大小是否会增加。不会的。

      哦,如果您想知道我的块是如何命名的,您可以将angular.json 中的namedChunks 设置为true,然后运行ng serve --prod,这样您就不会看到乱码编码字符了。

      干杯!

      【讨论】:

        猜你喜欢
        • 2020-05-03
        • 1970-01-01
        • 2019-06-17
        • 1970-01-01
        • 2017-11-29
        • 2022-06-29
        • 2020-04-21
        • 1970-01-01
        • 2013-08-09
        相关资源
        最近更新 更多