当前位置: 首页 > Web前端 > JavaScript

LazyloadbySAPSpartacus延迟加载设计原则

时间:2023-03-27 15:01:52 JavaScript

官方链接延迟加载,也称为代码拆分,允许您将JavaScript代码分成块。结果是您不必在用户访问第一个页面时加载整个应用程序的所有JavaScript。相反,仅加载给定页面所需的块。导航到其他页面时,会在需要时加载其他块。这种方法可以显着改善“交互时间”,尤其是当低端移动设备访问复杂的Web应用程序时。Spartacus延迟加载代码拆分方法是一种必须在应用程序构建时完成的技术。Angular提供的代码拆分通常是基于路由的,这意味着登陆页面有一个块,产品页面有另一个块,等等。由于Spartacus主要是CMS驱动,因此无法在构建时确定每个路由的实际应用逻辑。业务用户最终会通过引入或移除组件来改变页面结构。这就是为什么需要另一种延迟加载方法,Spartacus通过以下方式提供:LazyloadingofCMScomponentsLazyloadingofCMS-drivenfeaturemodules-CMS-drivenlazyloadingoffeaturemodulesDefiningDynamicImportsOnlyintheMainApplication动态导入是一种用于促进延迟加载并允许只能在主应用程序-主应用程序中使用的代码拆分。无法在预建库中定义动态导入。这是一个不幸的限制,导致客户必须添加一些应用程序代码。尽管自定义代码的数量保持在最低限度,但我们将在原理图库的未来版本中添加一项功能,以自动添加延迟加载模块。避免延迟加载代码的静态导入为了使代码拆分成为可能,您的静态JavaScript代码(主要应用程序包)不应包含任何您希望延迟加载的代码的静态导入。如果这样做,构建器会注意到代码已包含在内,因此不会为其生成单独的块。从库中导入符号时,这一点尤其重要。在撰写本文时(Angular9和Angular10),对于同一个库入口点,即使对于不同的符号,混合静态导入和动态导入也会打破该库入口点的延迟加载和摇树优化。如果你想这样做,它会在构建中静态地包含整个入口点。因此,强烈建议您为必须静态加载的代码创建特定的入口点,并为可以延迟加载的代码创建单独的入口点。延迟加载模块中的配置如果在延迟加载模块中提供了额外的配置,Spartacus会将其合并到全局应用程序配置中,以支持现有组件和服务的延迟加载场景。这在大多数情况下都能可靠地工作,尤其是当延迟加载的模块大多提供默认配置时。但是,如果过度使用它可能会导致问题,特别是当两个模块为配置的同一部分提供不同的配置时。可以通过在主应用程序中提供必要的覆盖来修复此类情况。此合并功能是通过默认启用的兼容性机制实现的,但您可以使用disableConfigUpdates功能标志禁用它。如果您正在开发一个新模块,该模块必须从延迟加载的模块挂接到配置,您应该改用ConfigurationService.unifiedConfig$。此功能将在下一节中介绍。UnifiedConfiguration提供了一种获取全局配置的方法,其中包括根配置和来自加载的延迟加载模块的配置。ConfigurationService.unifiedConfig$将统一配置公开为可观察对象,每次更改时都会发出新配置。例如,每次加载和实例化具有提供的配置的延迟加载模块时都会发生这种情况。所有配置部分按严格顺序合并,实际配置总是覆盖默认配置,根模块(即应用程序外壳)中定义的配置优先。以下示例显示了根应用程序和两个延迟加载模块中提供的不同配置的合并顺序,其中列表中的每个后续项都可以覆盖前一个:默认根配置延迟加载模块1的默认配置延迟加载moduleDefaultConfigurationfor2Lazy-LoadedModule1ConfigurationLazy-LoadedModule2Configuration根配置(始终优先)延迟加载模块中的提供程序延迟加载模块中提供的注入令牌对根应用程序中提供的服务不可见。这尤其适用于多提供的令牌,例如HttpInterceptors、各种处理程序等。为了缓解这个缺点,一些Spartacus功能,例如PageMetaService(使用PageMetaResolver令牌)或ConverterService(主要使用适配器序列化器和规范化器),使用后面的统一注入器场景。通过这样做,他们可以访问延迟加载的令牌,并可以利用它们来实现全局功能。对于不依赖于UnityInjector的机制(例如来自大多数非Spartacus库的功能,例如核心Angular库),建议您始终使用这些类型的令牌预加载模块。统一注入器统一注入器提供了一种注入令牌或多提供令牌的方法,同时考虑了根注入器和延迟加载函数的注入器。每次统一注入器的状态发生变化时,注入器都会公开一个可观察对象,该对象会为指定的令牌发出一组新的可注入对象。避免在延迟加载的模块中导入HttpClientModule一般来说,HttpClientModule应该在根应用程序中导入,而不是在库中。例如,如果你将它导入到一个延迟加载的库中,根库中的所有注入器对于来自延迟加载模块的HTTP调用都是不可见的。虽然在库中导入HttpClientModule在技术上是可行的,但在大多数情况下这并不是故意的,并且可能导致无法解释的错误,因此请记住这一点。延迟加载CMS组件延迟加载CMS组件的配置延迟加载CMS代码是通过在CMS映射配置中指定动态导入代替静态引用的组件类来实现的。这是一个示例:{cmsComponents:{SimpleResponsiveBannerComponent:{component:()=>import('./lazy/lazy.component').then(m=>m.LazyComponent)}}}技术细节导入支持使用可定制的组件处理程序(特别是LazyComponentHandler)。可以扩展此处理程序以自定义其行为、添加特殊挂钩或不同的触发器,或者实现可以选择性地重用现有处理程序的全新处理程序。模块的懒加载懒加载不仅仅是组件代码,核心部分(包括NgRx状态)只在第一次需要时加载一次功能提供共享的、懒加载的依赖模块当实现被重写时相关功能配置,CMS请求Components触发特性模块的懒加载。延迟加载模块的配置功能模块的动态导入(必须在主应用程序中定义)有关特定功能涵盖哪些CMS组件的信息(可以是库的一部分并静态导入)。此信息作为cmsComponents键下的字符串数组提供。这是一个例子:,'ManageBudgetsListComponent','ManageCostCentersListComponent','ManagePermissionsListComponent','ManageUnitsListComponent','ManageUserGroupsListComponent','ManageUsersListComponent',],},},}示例:[图片上传...(image.png-c043ed-1625895062179-0)]延迟加载模块中的组件映射配置延迟加载模块中的默认CMS映射配置应该以与静态导入模块完全相同的方式定义。Spartacus能够从延迟加载功能中提取CMS组件映射配置,并使用它来解析该功能所覆盖的组件类和工厂。这就是为什么可以并建议使用标准方法在惰性加载模块中提供默认CMS映射配置的原因。因此,可以根据需要动态或静态导入完全相同的模块和库入口点,并且仍然通过在应用程序中提供配置覆盖来从应用程序级别覆盖延迟加载的CMS配置。定义共享依赖模块允许您将一些逻辑提取到共享延迟加载模块中,通过在功能配置的依赖项属性中提供动态导入数组,可以将其定义为功能模块的延迟加载依赖项。这里有一个例子:>import('@spartacus/storefinder/core').then((m)=>m.OrganizationModule),//,,],},},}当延迟加载依赖于它的第一个特性时,这个未命名的依赖模块将只被实例化一次。它的提供者为传递给特征模块的组合注入器做出贡献,因此所有特征服务和组件都可以访问依赖模块提供的服务。组合注入器任何延迟加载的模块都可以从根应用程序注入器和依赖模块注入器注入(即有权访问)服务和令牌。这是可能的,因为每次实例化具有依赖项的功能模块时都会创建CombinedInjector。当一个被懒加载模块覆盖的CMS组件被实例化时,它可以注入(即访问)以下服务:在DOM元素上初始化延迟加载模块Spartacus提供了一个MODULE_INITIALIZER而不是AngularAPP_INITIALIZER来初始化延迟加载模块。APP_INITIALIZER机制在任何延迟加载发生之前完成应用程序的初始化,因此可能需要在加载时运行初始化逻辑的延迟加载功能无法这样做。MODULE_INITIALIZER注入令牌可用于在旨在延迟加载的模块中提供初始化函数。Spartacus延迟加载机制支持MODULE_INITIALIZER,因此MODULE_INITIALIZER提供的初始化函数将在它们定义的模块延迟加载之前运行。您可以像配置APP_INITIALIZER一样配置MODULE_INITIALIZER。这是一个例子:...从'@spartacus/core'导入{MODULE_INITIALIZER};...exportfunctionmyFactoryFunction(dependencyOne:DependencyOne){constresult=()=>{//在这里添加初始化逻辑};returnresult;}@NgModule({providers:[{provide:MODULE_INITIALIZER,useFactory:myFactoryFunction,deps:[DependencyOne],multi:true,},],})exportclassMyLazyLoadedModule{}准备库以使用延迟加载ProvidingFine-您的库中的细粒度入口点在您的库中提供了细粒度的入口点。从同一个入口点混合静态和动态导入会破坏延迟加载并影响tree-shaking,因此任何将直接用于动态导入的库都应该公开细粒度的帮助入口点以优化代码拆分。作为惯例,Spartacus公开功能的根入口点,例如@spartacus/orgainzation/administration/root。这种类型的入口点包含所有不应或不能延迟加载的代码。来自根入口点的模块应该在根应用程序中静态导入,这意味着它们将被预加载并在主应用程序块中可用。将静态代码与延迟加载代码分开当您使用Angular依赖注入时,注入器中的提供者列表在注入器初始化后不应更改。这种范式特别适用于任何多方提供的令牌、处理程序,尤其适用于任何Angular本机多方提供的令牌,例如HTTP_INTERCEPTOR、APP_INITIALIZER等。结果是延迟加载模块中的任何多方提供的令牌都将不可见到根或其他延迟加载块中服务的模块和服务,使用统一注入器注入的多提供令牌除外。一些Spartacus函数,例如PageMetaService或ConverterService,使用UnifiedInjector来了解可以延迟加载的标记,这样即使逻辑延迟加载函数,全局逻辑(例如SEO函数)也能可靠地工作。例如,可以在使用商店定位器功能时延迟加载商店定位器页面元解析器。Spartacus配置也通过提供配置块来定义,由于将延迟加载函数的配置贡献给全局配置的兼容性机制,配置块的处理方式略有不同。可以通过功能标志禁用此机制,将来默认关闭以支持统一配置功能。如果根服务看不到延迟加载提供程序的问题,您始终可以将此类代码包含在预先可用的静态链接模块中。建议在你的库中创建一个单独的入口点(按照惯例,命名为root,例如my-library/root),它包含最少的代码,将包含在主包中,并且从一开始就可用。