解锁多线程,让 Web 应用程序更流畅

Coaction - 一个高效、灵活的状态管理库,用于构建高性能、多线程的 Web 应用程序。

仓库:https://github.com/unadlib/coaction

动机

现代网络应用程序变得越来越复杂,突破了浏览器的极限。单线程 JavaScript 虽然功能强大,但通常难以满足复杂 UI、实时交互和数据密集型计算的需求。这种瓶颈会导致性能问题、界面滞后或无响应、请求连接受限,并最终影响用户体验。

虽然 Web Workers(或 SharedWorker)提供了实现并行性和提高性能的途径,但它们也带来了一系列新挑战。跨线程管理状态、高效同步数据以及维护一致的应用程序逻辑很快就会成为一项艰巨的任务。现有的状态管理解决方案通常无法满足这些特定需求,要么与工作线程耦合过于紧密,要么引入了阻碍开发人员工作效率的复杂抽象。

Coaction Concept

**Coaction 的创建源于对状态管理解决方案的需求,该解决方案真正涵盖了现代 Web 应用程序的多线程特性。**它认识到性能和开发人员体验不应该相互排斥。通过利用 Web Workers 和 Shared Workers 的强大功能,“Coaction”允许开发人员从工作线程中卸载计算密集型任务和状态管理逻辑,从而实现响应更快、更流畅的用户界面。

**Coaction 不仅能提高性能,还能为复杂应用程序提供更具可扩展性和可维护性的架构。** 该库的直观 API 灵感来自 Zustand,可确保流畅的学习曲线和高效的开发工作流程。 它对切片、命名空间和计算属性的支持促进了模块化和代码组织,使管理大型且不断发展的代码库变得更加容易。

**Coaction 与数据传输的集成开启了状态同步的新灵活性水平。**通过支持通用传输协议,它为各种通信模式和架构开辟了可能性,满足不同应用程序的独特需求。

**从本质上讲,Coaction 使开发人员能够构建下一代 Web 应用程序,而无需牺牲性能、开发人员体验或架构完整性。**它弥合了 Web 应用程序日益复杂的问题与跨线程高效、可维护和高性能状态管理需求之间的差距。它是一款专为开发人员设计的工具,他们致力于在并行性和响应性不再是可选项而是必需品的世界中创造卓越的用户体验。它还支持远程同步,使其也适合构建任何 CRDT 应用程序。

概念和特征

`Coaction` 旨在为 Web 应用程序中的多线程环境(如 Web Workers、Shared Workers,甚至跨进程和设备)中的状态共享和同步提供安全高效的解决方案。

主要特点包括:

  • 多线程同步:支持网页线程与工作线程之间共享状态,通过数据传输进行通用通信,开发者可以避免消息传递和序列化逻辑的复杂性。
  • 具有可选可变性的不可变状态:在 Mutative 库的支持下,核心提供了不可变的状态转换过程,同时允许在需要时使用可变实例进行性能优化。
  • 基于补丁的更新:通过基于补丁的同步实现高效的增量状态变化,简化其在 CRDT 应用程序中的使用。
  • 内置计算:支持基于状态依赖关系的派生属性,从而更容易从核心状态管理和检索计算数据。
  • 切片模式:轻松将多个切片组合到具有命名空间的存储中。
  • 可扩展中间件:允许中间件增强商店的行为,例如日志记录、时间旅行调试或与第三方工具的集成。
  • 与第三方库集成:支持 React、Angular、Vue、Svelte 和 Solid 等流行框架,以及 Redux、Zustand 和 MobX 等状态管理库。
  • 操作模式和基本原理

    这个库以两种主要模式运行:

  • 标准模式 在标准网页环境中,商店完全在网页线程内进行管理。默认情况下,补丁更新处于禁用状态,以确保在标准模式下获得最佳性能。
  • 共享模式 工作线程作为共享状态的主要来源,利用传输进行同步。网页线程作为客户端,通过存储异步访问和操作状态。
  • 在共享模式下,库会根据传输参数自动确定执行上下文,无缝处理同步线程。

    您可以在应用程序中轻松使用“Coaction”来支持多个选项卡、多线程或多处理。

    例如,对于跨多个选项卡共享的 3D 场景,您可以使用“Coaction”轻松处理它们的状态管理。

    https://github.com/user-attachments/assets/9eb9f4f8-8d47-433a-8eb2-85f044d6d8fa

    共享模式 - 序列图

    Image description

    表现

    测量(操作/秒)更新 50K 数组和 1K 对象,越大越好(查看源代码)。[Coaction v0.1.5 vs Zustand v5.0.2]

    Benchmark
    Coaction x 5,272 ops/sec ±3.08% (63 runs sampled)
    Coaction with Mutative x 4,626 ops/sec ±2.26% (83 runs sampled)
    Zustand x 5,233 ops/sec ±2.68% (79 runs sampled)
    Zustand with Immer x 253 ops/sec ±0.26% (93 runs sampled)
    
    The fastest method is Coaction,Zustand

    根据提供的性能数据,Coaction 的性能与 Zusand 的性能相当。但是,与 Zusand 搭配 Immer 相比,Coaction 搭配 Mutative 具有明显的性能优势。

    标准 Coaction 达到约 5,272 (ops/sec),标准 Zustand 达到约 5,233 (ops/sec),但最显著的差异出现在 Zustand 和 Immer 上,其急剧下降至仅 253 (ops/sec)。此外,Coaction 和 Mutative 达到约 4,626 (ops/sec)。这意味着 Coaction 和 Mutative 比 Zustand 和 Immer 快约 18.3 倍 (4626 / 253 ≈ 18.3)。数据清楚地表明,与 Zustand 相比,Coaction 提供了卓越的性能特征,与 Zustand 的 Immer 实现相比,这一优势尤为明显。

    我们还将提供更完整的基准测试。

    协同作用与条件之间的差异

    Coaction 的设计理念是提供必要且足够简单的 API,方便开发人员使用。因此,Coaction 继承了 Zustand API 设计的优势,并内置了 Zustand 未提供的功能支持。

    安装

    您可以通过 npm、yarn 或 pnpm 为 React 应用程序安装 `@coaction/react`。

    npm install coaction @coaction/react

    如果您想使用核心库而不使用任何框架,您可以通过 npm、yarn 或 pnpm 安装“coaction”。

    npm install coaction

    用法

    标准模式商店

    import { create } from '@coaction/react';
    
    const useStore = create((set, get) => ({
      count: 0,
      increment: () => set((state) => state.count++)
    }));
    
    const CounterComponent = () => {
      const store = useStore();
      return (
        

    Count: {store.count}

    ); };

    共享模式商店

    `counter.js`:

    import { create } from '@coaction/react';
    
    export const counter = (set) => ({
      count: 0,
      increment: () => set((state) => state.count++)
    });

    `worker.js`:

    import { create } from '@coaction/react';
    import { counter } from './counter';
    
    const useStore = create(counter);
    import { create } from '@coaction/react';
    
    const worker = new Worker(new URL('./worker.js', import.meta.url));
    const useStore = create(counter, { worker });
    
    const CounterComponent = () => {
      const store = useStore();
      return (
        

    Count in Worker: {store.count}

    ); };

    切片模式和派生数据

    import { create } from '@coaction/react';
    
    const counter = (set) => ({
      count: 0,
      // derived data without cache
      get tripleCount() {
        return this.count * 3;
      },
      // derived data with cache
      doubleCount: get(
        (state) => [state.counter.count],
        (count) => count * 2
      ),
      increment() {
        set(() => {
          // you can use `this` to access the slice state
          this.count += 1;
        });
      }
    });
    
    const useStore = create({
      counter
    });

    结论

    **从本质上讲,Coaction 使开发人员能够构建下一代 Web 应用程序,而无需牺牲性能、开发人员体验或架构完整性。**它弥合了 Web 应用程序日益复杂的问题与跨线程高效、可维护和高性能状态管理需求之间的差距。它是一款专为开发人员设计的工具,他们致力于在并行性和响应性不再是可选项而是必需品的世界中创造卓越的用户体验。它还支持远程同步,使其也适合构建任何 CRDT 应用程序。

    仓库:https://github.com/unadlib/coaction