React架构在大型商业应用中的应用

40
最近我们的公司使用React作为前端技术来构建巨型业务Web应用程序。说“最近”,意味着我们之前没有使用过React,而我们之前使用了大量AngularJS。说“巨型应用程序”,意味着它真的很大,非常动态,并且有许多不同的部件和功能。
因为我们将有许多巨大的组件,所有这些组件都扮演着非常重要的角色,并且内部有复杂的逻辑,而且我们希望它们易于插拔和可重用,因此我们希望它们尽可能与外部世界和我们应用程序的其他部分隔离开来,否则由于它们的大小和复杂功能,它们的开发和维护几乎是不可能的。这就是为什么我们决定在开发单独的组件本身时,至少在开始阶段,不使用Redux的原因,因为它会牺牲组件隔离性,并且当存在如此多的复杂组件时,会使整个应用程序数据流逻辑变得难以理解。尽管我认为我们的选择可能是错误的,因为正如我已经提到的,我们没有使用React的经验。
正如我已经提到的,该应用程序非常动态。我的意思是组件实际上是通过数据渲染的。我们使用各种配置提供程序类与我们的API端点交互,以获取应用程序配置的各个部分,如导航、页面、各种表单、列表等配置,然后尝试从该配置中读取组件进行渲染。
问题是,在经过几周的努力来学习React并发现解决我们问题的正确模式和通用解决方案之后,我们开始在团队中讨论,也许React不是适合我们的正确技术,因为它只是一个UI库,而不是框架,并且它并没有帮助我们很多,只是添加了一些渲染规则,有时我们必须打破这些规则以实现我们想要的动态性和组件独立性。
考虑到组件隔离和数据流管理,我个人听说了一种面向前端开发的语言Elm,其中具有相当强大的数据流架构,每个组件都有其自己的模型是独立于其他组件的,但我不知道是否值得一试,因为它可能很快就无法满足我们的大需求。我写这个问题的原因是希望从有丰富前端应用开发经验的人那里获得见解。我想知道是否可以使用React开发这样的应用程序,React是否适合处理如此复杂和动态的内容,我们是否真的需要Redux或其他什么东西,以及我们应该遵循什么路线、实践和思想。如果你正确理解了我的问题,那么我们所困扰的更多是架构方面,而不是技术方面。也许我们只是走了一条通向更多挣扎和复杂性而非生产力的道路。

4
自从你提出这个问题已经过去三年多了。你能告诉我们你使用React的经验吗? - Sheraz Ahmed
如果您能给我们提供更新,那就太好了。 - theprogrammer
9个回答

17
更新至2023年: 我们对这个问题的回答已经相当陈旧了。就目前而言,对于大型企业应用程序,我们更倾向于使用Webpack 5模块联邦(它在内部管理单例的React + ReactDOM + 其他组件)。虽然模块联邦是非常新的技术,但我们已经在大型企业应用程序中使用它,并且似乎效果非常好。我们还将MUI以及像我们的https://reactdatagrid.com表格这样的组件标记为单例,以便它们可以在主应用程序和子应用程序之间共享,使用语义化版本控制。
模块联邦也存在一些挑战。
  1. 首先,您必须将模块视为功能的实际黑盒而不是“共享组件”。您将它们解耦得越多,您的架构就会更加清晰。换句话说,将模块视为独立团队开发的独立应用程序,它们不依赖于周围的内容。
  2. TypeScript类型:由于模块联邦是对部署代码的运行时引用,而不是package.json构建时引用,因此您实际上没有代码中模块的类型。有些方法可以解决这个问题,包括联合类型,但我们发现如果您解耦模块,则这不是一个重要的问题。
  3. 微妙的版本差异可能会导致问题:例如,当您开发主机和远程主机时,如果它们具有引用库的不同版本,则在整个部署时,您将不知道哪个版本将“获胜”。对于具有大量环境的企业应用程序,这是一个额外的挑战,因为您不知道共享依赖项的版本存在于哪个环境中。这既是一个操作问题,也是一个技术问题。我们解决此问题的方法之一是在构建过程中进行管道检查以强制执行版本。虽然不是理想的方法,但比在生产中突然出现问题要好,因为某些引用库的版本在dev与production中不同。
  4. 避免耦合的诱惑:对于那些习惯于将模块视为具有大量属性和自定义的库的人来说,很难放弃这种范例。模块!=库。模块=应用程序。假设您有一个电子商务商店。您有一个产品模块和一个购物车模块。主机不应该知道购物车模块或产品模块。任何需要通信的地方都应该通过事件总线类型机制进行非常解耦。永远不要像跨模块的函数回调或属性钻取一样做事情。这会导致您的模块紧密耦合,并在团队更改其各自的模块时以意外的方式中断。
  5. 本地开发可能很困难:使用模块联邦,通常团队只开发相关模块,端到端测试需要在主机上加载所有其他模块以及您的模块。这并不容易做到,并且需要在本地开发过程中进行一些管道连接。其中一种方法是运行带有所有远程的主机,并用您的本地开发实例替换您的远程作为最终测试步骤。关于如何在此设置中使HMR正常工作存在一些问题,这是一个完整的答案,但它是可能的。

==== 结束更新

毫无疑问,React/Redux 可以(并且广泛地)用于开发您所描述的应用程序类型。您的描述中没有任何内容使您正在构建的东西如此独特,以至于 React 不能作为构建平台之一。我们正在与一个大型企业客户合作,该客户正在使用 React 构建他们的整个前端 - 包括100多个SPA(单页面应用)。这是一个由100多个开发人员组成的团队,历时2-3年。

我们构建项目的方式非常关键 -

首先,您需要选择一个 UI 组件库。以下是一些示例:

我们基本上选择其中之一,并根据自己的需求构建了一个组件库,因为我们的组件都是非常自定义的。

其次,我们创建了一个模块化架构,其中每个模块(单页应用程序)都是一个包含主容器组件和redux存储的npm软件包。

最后,我们有一个中央服务器软件包,其中注册了每个模块。 服务器软件包负责认证、授权、日志记录、路由等功能。

这个答案的要点不是为了建议如何构建一个大型的React应用程序,而是让您知道React可以(并且正在被)用于开发类似于您所描述的应用程序。


1
哇,这是一个不错的起点。很高兴听到有人做得对。谢谢你分享你的经验。你能更详细地解释一下你是如何实现那个单独的SPA(单页应用)概念的吗?你是如何将它们合为一个单元(应用)的呢?它们是某个更大的应用的一部分还是完全独立的应用?如果需要,它们之间是否可以相互通信? - Salivan
一个网站如何拥有100个单页应用(SPA)?你是指有一个复合用户界面,加载了多个包含SPA的iframe吗?否则,你描述的术语可能是错误的。 - plalx
1
每个单页应用程序都有自己的URL。"网站"可能不是描述它的正确术语。它更像是由多个单页应用程序组成的组织在线存在的集合。 - flexicious.com
1
我们几乎没有那个。在客户端,我们使用React Router或localStorage中的URL参数。在服务器上,我们使用Redis。在客户端,顶级Redux存储不相互通信,而我们的用例也不需要它们。 - flexicious.com
我不理解模块化SPA方法,它是否类似于ReactJS的开源代码? - Ashish Kamble
显示剩余3条评论

9

我现在正处于类似的情况。我的背景是大型桌面应用程序(ERP、LOB - WinForms、WPF),有1000多个模块,非常动态(超过70%的UI是由输入数据/配置生成的),添加新功能只需要扩展一些配置(不需要触及源代码)。

我正在深入研究当前的Web技术,并且越来越确信React不适合这种场景。React在小/中型应用程序中表现出色,其中您(和其他团队成员)手动开发每个页面/组件(而不是动态生成),并且希望拥有一个全局状态。但它不能帮助您构建大规模的应用程序 - 它只是UI库(因此没有支持模块、路由、表单绑定、http请求、静态类型(typescript)等)。让我惊讶的是,它没有支持样式阴影/封装(例如,您必须自己集成CSS模块)。最后,您必须不断地关注库版本控制(使它们始终协同工作确实耗费时间和精力)。

我有着很好的 Angular 2/4+ 经验,我认为,目前这是最适合该类应用程序的 最佳技术(如果您了解WPF,则非常相似)。它是一个完整的框架,准备好了直接用于扩展。您可以将应用程序分成独立的模块(指定哪些组件对外部可见),每个组件都有公共API(静态类型、输入/输出)和封装的CSS样式(没有其他干扰)。对于全局状态(已登录用户、全局配置等),您仍然可以使用ngrx/store库(实现Redux模式,并带有额外的好东西,例如“effects”,并且在Angular生态系统中集成得非常好)。

我尝试在Angular中做一些疯狂的事情(从后端配置动态生成整个应用程序),一切都像预期的那样完美地工作。


8
你在问题中指出了关键点-React是一个视图库,而不是一个应用程序框架。真正的问题是,React+Redux(或其他状态管理系统)是否适用于大型LOB应用程序。
我将分享一些团队在这个领域的经验。多年来,大型LOB应用程序一直使用MVC/MVP/MVVM设计模式。这些是经过试验和验证的模式,可以发布软件。再加上依赖注入,你就有了一个可模块化、可测试、可维护的应用程序。AngularJS(2.0+)基于这些原则,并深度利用了它们。因此,我们将AngularJS用于所有企业LOB应用程序。
另一方面,React是一个轻量级、敏捷的视图渲染器,非常适合小型应用程序和客户端界面(例如进行动态调查或简单的仪表板)。我们经常转向React和VueJS,因为完整的AngularJS堆栈过于复杂和笨重。

1
但是,通过适当的工程和架构,React生态系统是目前最适合大型应用程序的最佳框架之一。最好的例子就是Facebook本身。 - XPD
2
Facebook不是LOB,ERP系统。 - Marfu

7
开始在React中编写更复杂的应用程序可能会很困难,我完全理解这种感受!
正如你所说,React是一个UI库而不是事件框架。这就是为什么您通常需要使用一个库来处理事件,例如Redux。您明确表示决定不使用Redux(您甚至使用大写字母表示不使用:))。如果我是你,我会退一步并重新考虑这个决定。您说不使用Redux的原因是当使用Redux时,您无法轻松地使组件可插拔和可重用。我会认为这不是正确的。Redux与您的React组件完全解耦。Redux只处理接收事件和管理状态。从React组件的角度来看,它只是通过调用常规函数接收数据并发送事件。仍然可以进行单元测试、重用等操作。
我建议您再次考虑Redux并考虑这一点。如果您有更多问题,我很乐意提供帮助!

很高兴知道这里已经有人知道我们正在经历什么。说到Redux,我尝试使用它编写动态表单组件,但很快就感到非常困惑,因为我需要从各种来源向状态提供配置和数据,然后正确地呈现表单并使其各个部分同步。然后验证部分也开始起作用,还有各种表单字段类型,例如从在线API加载其选择的自动完成。然而,我仍然认为混淆可能是由于我缺乏对库/框架的经验和知识所致。 - Salivan
Redux是一个经过验证的库,它可以正常工作。如果您需要类似于Angular/Vue的体验,Mobx是一种响应式库。但是,您可能需要为其设计一个良好的架构。 - XPD

6
完全理解你在开始使用React和Redux时的感受。我们公司刚开始使用React时也处于同样的情况。首先,React的方法与其他框架不同。当然,它不是框架,只是一个库。您必须开始以React方式思考,即:React组件只呈现状态(就像您在图形卡上呈现场景一样,首先必须准备场景,然后才能呈现),组件所能做的就是分派操作,或更好地说是调用操作创建者。
您需要一些聪明的方法来存储状态,在这一点上,我建议使用Redux。
我们还使用TypeScript与组合React,Redux。您需要编写比纯JS更多的代码,但是在处理大型项目时,静态类型控制是无价的。
分离组件逻辑是React的本机方法…您必须将逻辑分离编写“Dummy components”,然后使用connect重用它们。或将值作为props传递。
我们正在使用Thunk中间件作为操作创建者,因为连接的组件将仅调用方法,并且逻辑在操作创建者中。您可以在那里访问整个应用程序的状态,然后可以获取某些内容,并根据结果调度不同的操作。
我喜欢React / Redux的实现异步调用等方式。首先设计组件以映射所有状态。

1)就像我没有数据 2)数据加载中 3)加载完成 4)加载错误

为此,您只需要在状态中使用一个信号量,并在render方法中进行一些检查。然后,创建一个操作创建器来加载数据,并根据进度分派描述进度的操作。

还有一个很酷的事情是,在react / redux应用程序中,您只有一个数据流,这对于新开发人员加入项目非常好。

对于UI,我们使用Material UI,是的,这个框架有些问题,但您可以处理它们。

我们还使用路由器在应用程序中进行导航。

一开始,我会避免服务器端渲染,因为您可以更轻松地从客户端渲染和初始状态开始。

当我们开始时,这个模板对我们很有用,其中所有内容都在一个项目中运行 JavaScriptServices

然后当然是伟大的Abramov教程。

对于设计组件非常有用Storybook

我们可以写很长时间关于为什么使用或不使用React...但是我可以说...对于我们来说,这是一个好选择,虽然一开始有些困难,但现在我们已经得到了很好的回报。


6

React, Redux将使事情更容易,因为当涉及到复杂应用程序时,您可以创建结构良好的数据对象。然后,您可以通过React及其Materials来管理完整的UI...这是正确选择的一些原因:

  1. 状态管理
  2. 树形结构数据处理
  3. 减少代码量
  4. 您将知道更改的位置(操作,规约)
  5. 您的组件仅负责UI事务

您需要做的就是结构化您的数据


4
我们使用Reactjs作为前端技术开发一个大规模的商业应用程序。 我们团队有30多人,产品中有15个以上的模块。
我采取的方法是开发一个通用的React项目,仅处理应用程序的身份验证,授权和路由,而所有其他组件都作为单独的npm React库进行开发。
为了开发这些库,我使用了https://www.npmjs.com/package/create-react-hook这个库。
此库生成带有示例应用程序的模板,可以用来测试我们的库。
以下是该项目的结构
-- 库1(使用create-react-hook开发)
-- 库2(使用create-react-hook开发)
...
-- 库n
-- 通用容器应用程序(使用create react app开发,并使用npm install使用上述库集)
这种方法的主要优点是开发人员只需专注于自己的npm软件包,然后可以分别开发和测试相关组件。 它还使部署变得非常简单,因为我们只需更新已测试版本的npm软件包,重新构建容器应用程序并进行部署,而不会影响应用程序的任何其他部分。
我们使用这种方法已经好几个月了,在庞大的团队中运行项目没有出现任何问题。 我认为对于其他人也可能有所帮助。

2
所以我想分享一下我在多家银行生产中使用的企业级React应用程序的经验。是的,你没听错。现在你可以想象一下,如果它与金融科技有关(我知道这并不总是这样),那么这个应用程序将有多么庞大。我们有巨大的模块(70+),具有复杂的逻辑,几乎处理了银行所需的大部分工作。模块既是隔离的又可重用。我将举一个例子,让您可以想象每个模块的大小。
- 卡片生产模块
1.批量卡生成 2.批量卡导出 3.批量卡请求 4.卡操作 5.卡操作审批 6.卡打印 7.新卡请求 8.PIN生成 9.PIN打印
这个应用程序是一个产品,而不是一个项目,作为产品,它是可配置的,甚至UI也是可配置的。我一直作为全栈开发人员在这个应用程序上工作。由于它相当老了,我们正在使用的状态管理库是flux。通过状态管理,开发速度有点慢,但权衡是更好的,因为我们不必担心状态管理。到目前为止,该应用程序已经能够处理巨大的变化和看似难以实现的事情。稳定性也是这段时间的关键因素。
在后端,我们使用Dot Net构建了支持MSSQL Server或Oracle的Restful服务,具体取决于客户的需求/可行性。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接