Reactant - A framework for building React web applications
2020-08-10
Motivation
React is a JavaScript library for building user interfaces, but building full applications with React still requires many architectural decisions: build configuration, state management, routing, testing, and business logic boundaries. Each team often develops its own interpretation of how a React application should be structured, which makes it harder to focus quickly on business logic. As application complexity grows, we need an application framework that is easy to understand and maintain.
For structured business logic, separation of concerns is essential. Clear responsibility boundaries help prevent UI logic and business logic from becoming tightly coupled. Business logic is one of the core assets of an application, so it should be maintainable and testable. Redux remains one of the most popular state libraries in React and fits React’s immutable state model well, but Redux is still only a state container. Teams still need a higher-level structure for managing state, modules, dependencies, and business behavior. We need a framework for scalable, loosely coupled, and maintainable React applications.
React is an excellent UI library, but Hooks alone do not solve every problem in large application development. We still need dependency injection, module boundaries, testable business logic, AOP-style extension points, and better support for DDD-style modeling. These are application architecture concerns beyond React itself.
This article does not argue that React itself must provide these features. React is already strong as it is. The real question is: Do we need a React framework?
Reactant was created to solve these problems. It is a framework for React.
Introducing Reactant
Reactant helps developers build extensible and maintainable React applications. It is based on TypeScript, but supports both TypeScript and JavaScript. For the best development experience, TypeScript is recommended. Reactant provides dependency injection, a modular model, immutable state management, dynamic module injection, and more. It is pluggable and highly testable. It can be used to build React applications for both web and native mobile, while still allowing developers to embrace OOP, FP, FRP, and the broader React ecosystem.
Reactant is inspired by several strong ideas from Angular. For example, it provides a dependency injection API similar to Angular’s. However, Reactant is not an attempt to copy Angular’s programming model into React. It provides a smaller and more concise API surface that is intended to cover common application development scenarios.
It provides an application architecture on top of React.
What problems does it solve?
Reactant is a progressive framework. As applications grow from simple to complex, it provides appropriate features at each stage. Its architecture also supports gradual upgrades and smooth evolution over time.
Better Immutable State Management
React advocates immutable state type management, and Redux clearly fits this. But the fact is that simple mutation update operations like MobX are increasingly in line with current trends. Therefore Reactant provides a new immutable state management model based on Redux and Immer, which incorporates similar API elements of MobX. And more importantly, it still maintains the immutability of state.
1 | () |
Modularization
After React introduced Hooks, the community increasingly embraced functional programming patterns. Hooks are excellent for decoupling rendering logic, especially in UI-focused code. For complex enterprise business logic, however, class-based module design can still be valuable. It can make parallel development, maintenance, and testing easier when multiple developers work on the same application. Classes are not the problem; poor module design is.
Therefore, Reactant advocates classes for module implementation. More importantly, Reactant defines Service Modules, View Modules, and Plugin Modules so their responsibilities and boundaries are clear. A Service Module is flexible and can serve as the base for many application architectures. A View Module defines the view component bound to the current module and acts as the rendering entry point. State from dependent modules can be injected into props through useConnector. A Plugin Module re-encapsulates Redux middleware and Context, providing a clear model for plugin API design.
In addition, Reactant provides a complete dependency injection API. It implements DI based on TypeScript decorator metadata, making it particularly easy to use.
1 | () |
Easy and Lightweight
Reactant has fewer than 30 APIs and fewer than 15 core APIs. After a short learning period, you can start using Reactant to build complex React applications.
The gzipped Reactant core runtime is less than 50 KB in the measured build. Reactant supports both code splitting and dynamic module injection, which helps large applications load only what they need.
Embracing React Ecosystem
Reactant is open. It abstracts several models on top of React and Redux while still supporting both ecosystems. Many third-party libraries can be used directly with Reactant or re-encapsulated as Reactant modules.
Better Development Experience
Reactant provides a simple routing module (reactant-router) and a persistence module (reactant-storage). When needed, you can also build custom modules on top of Reactant’s plugin model.
For debugging, devOptions supports both autoFreeze and reduxDevTools. When autoFreeze is enabled, any state-changing operation outside an @action method will throw an error. When reduxDevTools is enabled, Reactant activates Redux DevTools support.
Reactant will continue adding features that improve the development experience.
Benchmark Performance
In benchmark tests between Reactant and MobX+React, Reactant has an advantage in startup time and derived computation, while MobX+React has an advantage in value updates. Overall, the performance difference is not particularly significant for common application workloads. Because Reactant is based on Immer, it also provides performance-oriented options for rare bottleneck scenarios.
Reactant is committed to maintaining good performance while continuing to build a productive React framework.
Conclusion
Reactant was created to help React developers build maintainable and testable applications efficiently. Its goal is to reduce lifecycle cost and improve developer productivity.
As a new framework, Reactant has only been in development for a few months, and there is still significant work to do, including build tools, development tools, server-side rendering, and React Native CLI support.
If you are already familiar with React, you can read the Reactant documentation and use the Reactant CLI to quickly create a Reactant application.
Repo: