Spartacus 应用中 Lazy Loaded Module 初始化逻辑的实现方案

发布时间 2023-10-26 16:46:55作者: JerryWang_汪子熙

当我们谈论大型 Angular 应用程序时,一个重要的性能优化策略就是模块的懒加载。我们通过使用 Angular 的路由配置来实现模块的懒加载,这样可以在用户需要时再加载特定的功能模块,从而提升应用的性能。

然而,在这种情况下,我们可能会遇到一个问题,那就是如何在懒加载模块被加载时执行一些初始化逻辑呢?一种常见的做法是使用 Angular 的 APP_INITIALIZER,但这种方法有一个明显的缺点:APP_INITIALIZER 的机制是在任何懒加载发生之前就完成应用程序的初始化,因此,可能需要在加载时运行初始化逻辑的懒加载特性无法这样做。

为了解决这个问题,可组合商店前台(Composable storefront)提供了一个新的解决方案,那就是 MODULE_INITIALIZER。MODULE_INITIALIZER 应该被用来替代 Angular 的 APP_INITIALIZER,用于初始化懒加载模块。

MODULE_INITIALIZER 是一种注入令牌(injection token),可以在预计被懒加载的模块中提供初始化函数。由于 MODULE_INITIALIZER 支持可组合商店前台的懒加载机制,因此,使用 MODULE_INITIALIZER 提供的初始化函数将在定义它们的模块被懒加载之前运行。

你可以像配置 APP_INITIALIZER 一样配置 MODULE_INITIALIZER。下面是一个例子:

import { MODULE_INITIALIZER } from '@spartacus/core';

export function myFactoryFunction(
  dependencyOne: DependencyOne
) {
  const result = () => {
      // add initialization logic here
  };
  return result;
}

@NgModule({
  providers: [
  {
      provide: MODULE_INITIALIZER,
      useFactory: myFactoryFunction,
      deps: [DependencyOne],
      multi: true,
  },
  ],
})
export class MyLazyLoadedModule {}

虽然 MODULE_INITIALIZER 的主要用途是在一个模块被懒加载时运行,但如果它定义在的模块被配置为立即加载(即,在应用程序启动时加载,这是导入模块的默认方法),MODULE_INITIALIZER 函数依然会运行。如果一个设计用于懒加载的模块应用了立即加载的配置,那么 MODULE_INITIALIZER 函数将在 Angular 应用程序引导序列中运行。

由 MODULE_INITIALIZER 提供的初始化函数只在模块被加载时运行。这意味着,如果一个模块是懒加载的,初始化函数将在模块被加载之前运行,但它不会在应用程序被初始化时运行。如果一个模块被配置为立即加载,初始化函数只会在应用程序被初始化时运行。

如果任何初始化函数返回了一个 promise,那么应用程序的初始化或模块的加载将不会完成,直到 promise 被解决。如果有一个 promise 被拒绝,应用程序的初始化或模块的加载将被中断。