React 是一个用于构建 UI 的 JavaScript 库,但当我们要基于 React 开发应用时,往往要做很多的构建配置和很多其他库的选型(挑选和学习一个 React 状态库和路由器库等)。我们还需要考虑我们的业务逻辑应该如何抽象和结构化。每个 React 开发者都在实践着自己对 React 构建的认知,但这并不能让我们快速关注业务逻辑本身。随着应用业务规模的扩大,我们迫切需要一个易于理解和维护的框架。
而对于应用的业务逻辑结构化设计,关注点分离是个好主意。它要求明确责任边界,避免 UI 逻辑和业务逻辑混杂时可维护性低。我们在构建应用时,总是要关注业务逻辑。它是一个应用的业务核心价值之一。我们希望它易于维护、测试。Redux 仍然是 React 中最流行的状态库。它完全符合 React 不可改变的原则。Redux 只是一个状态容器,而我们往往不知道如何真正管理这些状态。我们需要一个可扩展、松散耦合、易维护的 React 应用框架。
React 是一个优秀的 UI 库,但就算 React 有了 hooks,它依然不足以解决我们在开发大型应用中的种种问题。我们依然没有模块依赖注入,我们没有很好的 AOP 实践模型,我们没有达到很好最小化模块系统抽象的可能,我们也无法更好的实践 DDD,等等。这些问题都是 React 之外,我们需要思考和解决的。
当然,这里我并不是要讨论 React 是否需要加入这些特性,它已经足够优秀了。这里真正要讨论的是:我们是否需要一个 React 框架呢?
为了解决这些架构问题,Reactant 应运而生 ——— 它是一个 React 框架。
Reactant 能高效地构建可扩展、可维护的 React 应用。Reactant 基于 TypeScript,但它同时支持 TypeScript 和 JavaScript (为了更好的开发体验,推荐使用 TypeScript )。Reactant 提供了依赖注入、模块化模型、不可变状态管理、模块动态化等功能。它是可插件化、高度可测试的。它不仅能够快速构建 React 应用( Web 和 Native Mobile ),还带来了一些新的 React 开发体验。Reactant 也保持恰当的灵活性。使用了 Reactant,你依然可以拥抱 OOP,FP,FRP 等编程范式,你依然能够拥抱整个 React 生态。
Reactant 受到 Angular 不少优秀特性的启发,例如 Reactant 提供和 Angular 相类似的依赖注入的 API 。但 Reactant 并不是 Angular 编程思想在 React 框架上的一次复制,Reactant 提供了更少更简洁的 API,它足够应付各种开发应用的编程场景。
它是对 React 的一次完整架构。
Reactant 是一个渐进式的框架。在开发应用从简单到复杂的过程中,它都能在每个阶段提供适合的 feature,基于它的系统架构设计也能进行各种渐进式的平滑升级与演进。
React 更倡导的 immutable 状态类型管理,Redux 显然符合它。但事实上,类似 MobX 这样简洁的突变的更新操作越来越符合当下流行的趋势。因此 Reactant 基于 Redux 和 Immer 提供了新的不可变状态管理模型,它融合了 MobX 相似的 API 元素,更重要的是它依然保持了状态的不可变性。
@injectable()
class TodoList {
@state
list: Todo[] = [];
@action
addTodo(text: string) {
this.list.push({ text, completed: false });
}
}
虽然 React 推出了 Hooks 后,似乎整个 React 社区都越来越推崇函数式编程,但是在复杂的企业级业务中,函数式编程未必上最佳的解决方法。当然,如果只在构建 UI 上,Hooks 确实带来很好的渲染逻辑解耦的解决方案。但在业务逻辑领域,我们有更好的选择,尤其在一个企业级应用中的多人协作开发,事实上基于 class 的模块设计常常带来并行开发和易于维护与测试带来。类并不是有害的,错误的模块设计才是有害的。
因此在 Reactant 提倡使用 class 进行模块实现,更重要的是 Reactant 定义了 Service Module,View Module,Plugin Module,使它们更明确职责与边界。任何一个模块都可以是 Service Module,它是灵活的,许多不同应用的架构都可以基于它进行; View Module 必须定义当前 Module 绑定的视图组件,它是视图模块的渲染入口,它依赖的模块状态都将通过 useConnector 进行直观地 Props 注入; Plugin Module 是一个完整的 Redux 的中间件以及 Context 的再封装,它提供了一个设计插件的模型,它让插件 API 简洁无比变得可能。
此外,Reactant 提供完整的依赖注入 API 。基于 TypeScript 装饰器的 metadata 来实现的 DI,使得使用它变得特别简单。
@injectable()
class AppView extends ViewModule {
constructor(public counter: Counter) {
super();
}
component() {
const count = useConnector(() => this.counter.count);
return (
<button
type="button"
onClick={() => this.counter.increase()}>
{count}
</button>
);
}
}
Reactant 的 API 不超过 30 个,核心 API 更是少于 15 个。无须过多的熟悉和适应,你就能快速上手 Reactant,并用它来开发任何复杂的 React 应用。
在运行时,Reactant 的核心代码 gzip 压缩小于 50KB 。Reactant 不仅支持代码拆分,它也支持模块动态注入,这非常有利于许多大型应用程序最小化运行。
Reactant 是开放的,它基于 React 和 Redux 的 Reactant 抽象了一些模型。这些 API 带给开发者便利的同时,它也支持了 React 和 Redux 的生态系统。很多优秀的第三方库能直接在 Reactant 上使用或者进行再封装,这给 Reactant 应用带来无限可能。
Reactant 提供了更简洁的路由模块(reactant-router)和持久化模块(reactant-storage)。如果有必要,你可以基于 Reactant 插件模块开发出任何你需要更好的模块 API 。
在开发调试中,devOptions 支持 autoFreeze 和 reduxDevTools 两个选项。当 autoFreeze 启用时,任何不在 @action 装饰过的函数中改变状态的操作都将报错;当 reduxDevTools 启用时,Reactant 将激活对 Redux 的 DevTools 的支持。
Reactant 还很新,更多的提升开发体验的特性还在进行中。
Reactant 和 MobX+React 的基准性能测试中,Reactant 在启动时间和衍生计算上具有优势,而在值的更新上 MobX+React 更具有优势,总体而言,两者性能差别没有特别明显。因为 Reactant 基于 Immer,因此当遇到极少数极端的性能瓶颈,Reactant 也提供的性能优化的解决方案。
Reactant 致力于保持良好性能的情况下,持续构建一个具有生产力的 React 框架。
Reactant 的初衷是希望能够帮助 React 开发者们能进行高效地构建和开发一个可维护、可测试的应用。Reactant 的目标就是最小化系统的寿命成本并最大化开发者的生产力。
作为一个全新的框架,Reactant 才开发了几个月,还有很多工作需要完成,包括构建工具集,开发工具集,SSR,以及 React Native CLI,等等。
如果你已经熟悉 React,那么你只需要快速阅读 Reactant 部分文档后并使用 Reactant CLI 快速构建 Reactant 应用,你就可以开启你全新的 React 应用开发体验。
Repo:
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.