Redux-如何在大型应用程序中组织存储

时间:2020-01-15 21:32:20

标签: angular redux ngrx ngrx-store state-management

我们正在将Angular 7与NGRX结合使用来开发SPA。几个月前,我们已经迁移到NGRX,主要用于身份验证和会话数据。之后,我们也开始移动其他功能。我将描述这个问题以及我们头脑中有什么解决方案及其弊端。得知您如何解决此问题(如果有)或解决问题的想法,我将非常感激。

使用Redux(NGRX)的动机

  1. 我们拥有需要在多个组件之间共享的数据。通过属性共享是不可能的,因为我们的组件被Angular路由器隔开。
  2. 通过重用已加载的数据(例如Auth / Session)来减少请求数
  3. 性能-组件使用ChangeDetectionStrategy.OnPush时Angular的执行速度显着

业务问题

在我们的应用程序中,我们有6个模块。每个模块至少具有10个功能(页面)。我们之间只有很少的共同细节。

Redux Store的第一步

由于我们的主要问题是#1和#2(如上所述),所以我们从以下商店结构开始:

 {
  "authentication": {
    "isLoading": false,
    "error": {},
    "token": "auth-token"
  },
  "session": {
    "userDetailsIsLoading": false,
    "userDetailsData": {},
    "userDetailsError": {}
  }
}

到目前为止,太好了。就像所有带有增加/减少/重置计数器的Redux教程一样。

迁移模块功能

这是有趣的开始,因为我们在应用程序内部有很多功能(6个模块* 10个功能= 60+)。 第一个决定是使用reducer per feature而不是reducer per entity,因为我们拥有的页面具有相同的实体类型,但是使用不同的过滤器获取。由于大量数据,我们正在服务器端过滤数据。 例如:最近10篇帖子,前10篇帖子-都在同一页面上

因此,我们扩大了我们的商店,增加了更多的减速器:

{
   "authentication": {},
   "session": {},
   "blogs-list": {},
   "blogs-add": {},
   "administration-users": {},
   "administration-add-user": {}
}

问题

动作类型冲突

是的,我们使用格式[Feature] Action Description时遇到了第一类碰撞。 为了解决这个问题,我们决定添加使用命名空间[Module][Feature] Action Description

大商店

那是最大的问题。整个商店变得很大。商店干净时这不是问题,但是经过几次导航后,商店中包含许多不需要的数据。

我们考虑的解决方案

延迟加载

Angular允许延迟加载所谓的NGRX Features。这意味着我们可以仅从共享数据(身份验证,会话)开始,一旦打开模块,所有的reducer都将添加到存储中。该解决方案部分地解决了该问题。如果您导航到所有模块,那么商店将再次变大。

切换到实体简化器

从理论上看这很容易,但是在实践中却很难。正如我提到的,我们有一种仪表板,其中显示相同的实体,但使用不同的过滤器和分页获取。在头脑中,我有一个想法针对这些情况使用不同的减速器,例如:

{
   "latest-entities": {
       "isLoading": bool,
       "data": {},
       "error": {},
   }, 
   "most-popular-entities": {
       "isLoading": bool,
       "data": {},
       "error": {},
   }
}

但是这里还有另一个缺点。我们曾经将过滤器保留在功能存储中,并且一旦我们更改过滤器,效果就会触发数据重新加载。切换到此体系结构,我们将数据重新加载的责任移至containersContainer将负责向商店latest-entitiesmost-popular-entities分发动作。这个解决方案也将越来越大。通过重组reduces和store无法完全解决该问题。

不要将功能部件移至Redux,而是将其保存在容器中

我们可以将功能逻辑保留在containers中,并将redux仅用于跨模块数据,例如会话,身份验证和通知。这也是一种解决方案,但有其缺点。我想保持应用程序的一致性,并且不要在容器和存储中都包含业务逻辑。

重置商店

为使商店变小,我们可以创建一个操作,将商店重置为初始状态,一旦不使用该功能便将分派该商店。这是一个示例:

  public ngOnDestroy(): void {
    this.store$.dispatch(new BlogStoreActions.DestroyAction());
  }

1 个答案:

答案 0 :(得分:1)

我无法发表评论,但是您的问题让我感到好奇,因此我将其提交给了Twitter和ngrx维护者之一。

以下是回应(来自Wes Grimes):

如果商店太大,那么也许是时候重新考虑从客户端获取什么数据了。您真的是完整的数据模型还是配对的向下视图模型就足够了?一次批量获取数据。获得50,然后根据需要再返回50(延迟加载)。

还可以利用角度中的延迟加载特征模块,将forFeature与NgRx结合使用,然后仅加载所需的部分存储。但是再说一次。如果需要考虑大小,请考虑最小化客户端数据并将繁重的工作转移到后端。

链接:

https://twitter.com/qkwrv/status/1217593781282734080