此功能在 3.2 版本引入。
代理外观是一种灵活的机制,可以从可延迟加载的功能模块中抽象出功能,这种功能抽线,可以对应用程序的任何部分完成,例如组件、服务、指令等。
在延迟加载的配置中,Facade 被定义为一个非常薄的层,它只是一个带有一些元数据的空类,并且这个 Facade 动态地创建了一个 Facade 实现的代理。
下图是一个例子:
一旦代码的任何部分访问代理外观的任何方法或属性,必要的功能就会在暗地里加载和初始化,并将调用代理到实际实现。
根据设计,代理外观对于延迟加载和急切加载场景是完全透明的。 对于预加载场景,当代码静态链接时,实际实现掩盖了代理提供程序,并且无需任何代理层即可直接访问。
feature module
功能模块允许您将核心业务逻辑与组件一起封装,并在请求任何组件或需要某些逻辑时立即加载它们。 代理外观利用功能模块配置来了解哪个功能包含外观的实现。 每当访问功能的属性或调用方法时,都会在后台加载和初始化功能。
Defining Proxy Facades
本节介绍如何在根入口点中定义代理。
如前所述,代理外观是一个非常薄的层,由一个 JavaScript 类和一些元数据组成,这些元数据应该在根注入器中可用。 然后可以在应用程序的任何预先加载或延迟加载部分中使用这个轻量级注入器。
下面是一个 UserAccountFacade 代理定义的例子,它有一个 get 方法并由 USER_ACCOUNT_CORE_FEATURE 实现:
@Injectable({
providedIn: 'root',
useFactory: () =>
facadeFactory({
facade: UserAccountFacade,
feature: USER_ACCOUNT_CORE_FEATURE,
methods: ['get'],
}),
})
export abstract class UserAccountFacade {
abstract get(): Observable<User | undefined>;
}
上文所示这种轻量级的 Facade 模块是急切加载包的一部分(通常是根入口点,在默认 Spartacus 库的情况下),而其具体实现(UserAccountService),是在延迟加载的块中提供的。延迟加载的块通常实现在库的 core 文件夹下。
下面是一个实现的例子:
@Injectable()
export class UserAccountService implements UserAccountFacade {
// ...
get(): Observable<User | undefined> {
// ...
}
}
如何在懒加载的 chunk 里为该 facade 提供实现:
export const facadeProviders: Provider[] = [
UserAccountService,
{
provide: UserAccountFacade,
useExisting: UserAccountService,
},
];
为方便起见,外观同时作为 UserAccountFacade 和 UserAccountService 提供。 这使得覆盖更容易一些(只有 UserAccountService 实现必须被覆盖),并方便急切加载场景,其中 UserAccountFacade 提供者将覆盖默认的外观代理提供者。
实现细节
FacadeFactory 创建一个简单的外观代理类,该类基于方法和属性的配置。
所有方法都必须返回 Observable 对象,否则会被忽略。
访问任何属性(必须是 Observable)或调用任何方法都会触发加载由外观代理引用的功能模块。 加载特征后,特征模块注入器用于注入外观实现,该实现在特征模块内部提供,与外观代理具有相同的令牌。 然后调用实现中的相应属性或方法并将其移交给调用者。
也可以使用 async 标志设置为 true 来创建外观工厂。 这种门面会在功能模块初始化后短暂延迟对门面实现的调用,这允许异步门面初始化。 当门面使用异步初始化的 NgRx 存储时,这是推荐的设置。
Default Approach in Spartacus
在 Spartacus 中,外观代理默认定义在根入口点中,这意味着它们静态链接到主包。 因此,以最小的开销,任何组件或服务都可以注入其轻量级代理令牌,而无需知道 Facade 是否是任何延迟加载或预先加载功能的一部分。
通常,facade 定义引用 feature_name_CORE 特征,而默认情况下,特征提供在 feature_name 特征下,并且 feature_name_CORE 用作 feature_name 的别名。 通过这种设计,外观代理在默认配置中工作,其中核心、occ 和组件模块被捆绑到一个延迟加载模块中。 另一方面,很容易拆分这个模块,只加载核心部分(没有组件)来实现细粒度的延迟加载。 这可以通过为 feature_name_CORE 功能定义配置和延迟导入来完成。
后续我会通过一些具体的例子来说明。
更多Jerry的原创文章,尽在:"汪子熙":
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。