NgRx 22 发布:引入 Resource Extensions 和动态 DeepSignal,增强 Angular 状态管理能力
面向 Angular 的响应式状态管理框架 NgRx 发布了 22 版本,新增用于定制 Angular Resource API 的工具、支持联合类型的动态 DeepSignal、新的 SignalStore 类型辅助工具,并兼容 ESLint v10。 此次更新最重要的新功能是 Resource Extensions
NgRx 是一个面向 Angular 的响应式状态管理框架,其 22 版本现已推出。新版本带来了用于定制 Angular Resource API 的工具、支持联合类型的动态 DeepSignal、新的SignalStore类型辅助工具,并且兼容 ESLint v10。
本次更新中最受关注的新能力是 Resource Extensions,它通过一个全新的实验性入口@ngrx/signals/resource对外提供。Angular 的resource 和 httpResourceAPI 在重新加载时会把value() 重置为 undefined读出来,而资源一旦进入错误状态,再读取该值就会抛出异常。Resource Extensions 的做法是在现有 Resource 外面包一层,仅对这些行为做出调整,资源原有的类型则保持不变。
新版本内置了 4 种扩展,同时提供provideResourceExtensions函数,让开发者可以在应用、路由或组件级别注册默认扩展。Marko Stanimirović 在此前的 RFC 中解释过,调整错误处理行为也是把 Resource 与SignalStore进一步集成的前提条件,原因在于“资源一旦进入错误状态,后续任何一次patchState调用都会抛出异常,因为它在内部会读取value()”。
这一提案得到了社区的正面回应。Manfred Steyer 回复“非常棒”,并提出可以增加一个用于激活资源的 Signal。还有一位评论者希望该功能与 SolidJS 的createResource保持一致,比如允许在 loader 中访问当前值。
DEV 上的一篇社区综述指出,借助 Angular 的snapshot()加上额外的状态处理逻辑,同样能做到相近的效果。不过换用 Resource Extensions 之后,「可以直接操作 Resource 本身」,值既能保持可写,也能留住httpResource更具体的类型信息。
TanStack Query for Angular 也具备类似本领:查询键一旦变化,用 placeholderData: keepPreviousData 就能把之前的数据留下来。另外,社区维护的 NgRx Toolkit 里那个 withResource,早就支持在读取undefined时不抛异常、沿用旧值,还支持针对 SignalStore 的错误处理策略;相关错误处理能力从 v20.6.0 起就已经有了。
DeepSignal 在 NgRx 22 里还能跟着类型动态变。以前某个状态切片用联合类型描述不同状态(比如表示「尚未加载」的那种),它会被压成一个扁平的 Signal。如今对象字面量里的每个成员各自拥有独立的 DeepSignal,开发者可以在使用in运算符把类型范围收窄之后,再去访问对应的信号。
这一版还新增了SignalStoreFeatureType工具类型,用来提取 Feature Factory 的状态及其成员。自定义 Feature 因此能直接拿这些类型当输入复用,不用再手动声明一遍。其余更新包括:@ngrx/store-devtools 新增 actionCreators增加了一个选项,可以从 Redux DevTools 分发 Action;@ngrx/eslint-plugin兼容 ESLint v10 了,同时 ESLint v8 和旧版.eslintrc配置格式不再支持;NgRx 文档网站则多了浅色主题。
想升级到新版本,需要 Angular 22、TypeScript 6.0,以及 RxJS ^6.5 或 ^7.5。开发者可以执行ng update @ngrx/store@22来完成升级;项目如果只用 SignalStore,执行ng update @ngrx/signals@22即可。大多数破坏性变更都配了自动迁移工具,细节可查 v22 迁移指南和变更日志。团队还得留意,Angular 22 改了 Resource 的时序行为。有开发者报告过相关测试失败,这个问题后来被写进 Angular 发布说明,列为一项破坏性变更。
有开发者认为,NgRx Signals 是新的做法,用着很顺手。以往接状态管理要五个文件,现在一般一个文件就够,全部或大部分相关功能都能放在一起。
另一位用户则指出,
现代 Angular 比早期的 v2 版本好用太多(甚至比其刚上手时的 v4 版本也好得多)。很多过去非写不可的样板代码,现在用不着了。而且 RxJS 和 NgRx 也变得越来越不是必需品,这是好事。
NgRx 是社区驱动的开源框架,用来构建响应式 Angular 应用。它靠 Store 和 Effects 做全局状态管理,也提供基于 Signal 的 SignalStore。项目由 Nx 和 CodeRabbit 赞助,源码放在 GitHub 上。