React architecture for a huge business application

Update For 2023:
Our answer to this question is quite old, and as of today, for large Enterprise applications, we prefer to do Webpack 5 module federation (which manages the singleton React + ReactDOM + others intrinsically). Although module federation is very new, we are using it in large enterprise applications and it seems to work very well. We also mark MUI as well as components like our https://reactdatagrid.com grid as singletons so they are all shared among the host app + sub apps using semantic versioning.

There are a few challenges with module federation.

  1. First, you have to think of modules not as “shared components” but as literal black boxes of functionality. The more you decouple them the cleaner your architecture will be. In other words, think of modules like standalone applications developed by independent teams that do not depend on whats around them.
  2. Typescript types: Since module federation is a runtime reference to deployed code as opposed to a package.json build time reference, you dont actually have types of the modules in your code. There are ways around it, including federated types, but what we have found is if you decouple your modules, this is not a significant concern.
  3. Subtle version differences can cause issues: For example, when you develop the host and remote, if they have different versions of the referenced libraries, you wont know which one “wins” when the whole thing is deployed in unison. For enterprise applications with a large number of environments, this is an additional challenge because you dont know what version of the shared dependencies exist in which environment. This is as much an operational issue as it is a technical one. One of the ways we have resolved this is to have pipeline checks in the build process that enforces versions. Not ideal, but better than things suddenly breaking in production because the version of some referenced library is different in dev vs production.
  4. Avoid the allure of coupling: For people who are conditioned to think of modules as libraries with tons of properties and customizations, its hard to let go of that paradigm. Modules != libraries. Modules = applications. Let’s say you have a e-commerce store. You have a product module and a cart module. The host should know nothing about the cart module or the product module. Any communication that needs to happen should be very decoupled via an event bus type mechanism. Never do something like function callbacks or prop drilling across modules. This will cause your modules to be tightly coupled and break in unexpected ways when teams make changes to their respective modules.
  5. Local development can be difficult: With module federation, often teams only develop the module in question, end to end testing requires all the other modules to be loaded in the host along side your module. This is not easy to do, and requires some plumbing on local development. One of the ways to do this is to run the host with all of its remotes and replace your remote with your local development instance as a final testing step. There are some issues around getting HMR to work with this setup, which is a whole answer in itself, but its possible.

==== End Update

There is absolutely no question that React/Redux can (and is widely) used to develop the kind of applications that you describe. Nothing in your description makes what you are building so unique that it excludes React as a platform for building it. We are actively working with a large enterprise customer who is building their entire front end – with 100 + SPA (Single page applications) in React. This is a team of over 100 developers over a 2-3 year project.

The way we structured this has been crucial –

First, you want to choose a UI component library. A few examples below :

We basically took one of these and built a component library off of them, because our components are very custom styled.

Second, we created a modular architecture, where each module (SPA) is an npm package with a main container component and redux store.

Finally, we have a central server package, where each of the modules is registered. The server package is responsible for authentication, authorization, logging, routing, etc.

The essence of this answer is not to advise on how to structure a large React application, but to let you know that React can be (and is being) used to develop applications similar to what you are describing.

Leave a Comment