V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
unadlib
V2EX  ›  程序员

Reactant: 一个渐进式 React 框架

  •  1
     
  •   unadlib · 2020-08-16 09:55:41 +08:00 · 1566 次点击
    这是一个创建于 1568 天前的主题,其中的信息可能已经有所发展或是发生改变。

    动机

    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 简介

    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,基于它的系统架构设计也能进行各种渐进式的平滑升级与演进。

    更好的 immutable 状态管理

    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 不仅支持代码拆分,它也支持模块动态注入,这非常有利于许多大型应用程序最小化运行。

    拥抱 React 生态

    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:

    https://github.com/unadlib/reactant

    14 条回复    2020-08-17 19:14:40 +08:00
    loading
        1
    loading  
       2020-08-16 11:55:00 +08:00
    是框架还是脚手架?
    unadlib
        2
    unadlib  
    OP
       2020-08-16 12:00:51 +08:00
    是一个框架,附带脚手架。
    unadlib
        3
    unadlib  
    OP
       2020-08-16 12:01:17 +08:00
    @loading 是一个框架,附带脚手架。
    loading
        4
    loading  
       2020-08-16 12:04:32 +08:00
    如果要推广开,可能需要双语文档。
    AlexaZhou
        5
    AlexaZhou  
       2020-08-16 12:23:47 +08:00
    感觉这个渐进式,上手起点还不够低

    如果能像 vue 那样,在原本的 html 里面引入一个 js 就能让页面动态化,推广会简单很多
    hronro
        6
    hronro  
       2020-08-16 13:39:34 +08:00 via iPhone
    看你还在用 decorator 这种不稳定的 API 我就不打算用了,更别提你还在用 class API
    zlgodpig
        7
    zlgodpig  
       2020-08-16 16:06:12 +08:00 via Android
    装饰器因为规范制定的问题,的确很尴尬。但是业务模型用 class 的方式写没毛病,单说业务表达的,比 hooks 这套直观多了
    unadlib
        8
    unadlib  
    OP
       2020-08-16 16:38:36 +08:00
    @loading 谢谢你的建议。
    unadlib
        9
    unadlib  
    OP
       2020-08-16 16:43:26 +08:00
    @hronro decorator 确实到现在才 Stage2 。确实太操蛋了。不过我这里的处理逻辑很多后置的,所以本质上就算 decorator 提案再次大概也 没问题。另外 ng 和 MobX 其实也算流行了不少了。我想 decorator 每个人都有自己的理解,我也理解你的的担忧。


    有兴趣可以来探讨一下,https://github.com/unadlib/reactant/issues/18
    unadlib
        10
    unadlib  
    OP
       2020-08-16 16:46:55 +08:00
    @zlgodpig 是的,我想轻量级的 Context+Hooks,其实限制还是比较大的。eslint-plugin-react-hooks 其实能 cover 的也是极其有限的,毕竟不是语言层级支持的范式。
    taowen
        11
    taowen  
       2020-08-17 08:56:58 +08:00
    ruby on rails 这样的框架当年能一炮而红,其推广手法上是很值得学习的。你得找个大点的 demo,用框架快速搞出来,显著提升了效率,然后录制成视频,让别人 5 分钟看完。从开发者要完成的任务出发,强调帮你全搞定。

    lib 的推广则是反过来的。从自己有什么出发,强调自己填补了哪一项空白。更偏向小而美。
    Qinmei
        12
    Qinmei  
       2020-08-17 10:06:07 +08:00
    decorator 确实不怎么敢用, 另外 react 肯定是要拥抱函数式的,现在如果继续用注入, 那跟 react 的区别会越来越大, 到时候就不是类 react 而是类 angular 了
    unadlib
        13
    unadlib  
    OP
       2020-08-17 19:13:13 +08:00
    @taowen 感谢你的建议。
    unadlib
        14
    unadlib  
    OP
       2020-08-17 19:14:40 +08:00
    @Qinmei 是的。事实上如果把 React 只当成一个 Renderer,越到后面越不太需要考虑到 React 本身的 feature,可维护性才是重点。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2602 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 03:42 · PVG 11:42 · LAX 19:42 · JFK 22:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.