npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@do-md/zenith

v2.0.2

Published

Engineering-grade React state management powered by Immer

Downloads

420

Readme

Zenith

工程化的 React 状态管理 · 融合 Zustand 的极简与 MobX 的组织力

npm version License: MIT TypeScript Powered by Immer Gzipped Size

English | 简体中文 | 日本語


⚡️ 简介

Zenith 是一个 基于不可变数据(Immutable Data)的自动化响应模型

它旨在解决 React 状态管理中的一个经典矛盾:如何在享受 MobX 自动派生能力的同时,保留 Redux/Immer 快照的可预测性

  • 🛡️ Immer 的不可变性 — 符合 React 直觉,数据结构共享,高性能快照。
  • ⚡️ MobX 的响应力 — 响应式计算属性、自动依赖追踪,多层级链式派生,拒绝无效渲染。
  • 🎯 Zustand 的极简 — 零模版代码,直观的 API。
  • 🏢 企业级工程化 — 强制封装业务逻辑,拒绝 UI 层随意修改状态。

🚀 30 秒上手

1. 定义 Store

使用 class 组织逻辑,用 @memo 定义高性能计算属性。

import { ZenithStore, memo } from "@do-md/zenith";

class TodoStore extends ZenithStore<State> {
  constructor() {
    super({ todos: [], filter: "all" });
  }

  // ⚡️ 计算属性:依赖自动追踪,结果自动缓存
  // 只有当 todos 或 filter 变化时,filteredTodos 才会重新计算
  @memo((s) => [s.state.todos, s.state.filter])
  get filteredTodos() {
    const { todos, filter } = this.state;
    if (filter === "all") return todos;
    return todos.filter((t) => t.completed === (filter === "completed"));
  }

  // 🔗 链式派生:基于上一个计算属性
  @memo((s) => [s.filteredTodos])
  get stats() {
    return {
      total: this.filteredTodos.length,
      active: this.filteredTodos.filter((t) => !t.completed).length,
    };
  }

  // 🔧 业务 Action:直接修改 Draft,Immer 负责生成不可变数据
  addTodo(text: string) {
    this.produce((draft) => {
      draft.todos.push({ id: Date.now(), text, completed: false });
    });
  }

  toggle(id: number) {
    this.produce((draft) => {
      const todo = draft.todos.find((t) => t.id === id);
      if (todo) todo.completed = !todo.completed;
    });
  }
}

2. 在组件中使用

像 Zustand 一样使用 Hooks,具备完整的 TypeScript 类型推导。

const { StoreProvider, useStore, useStoreApi } = createReactStore(TodoStore);

function TodoApp() {
  return (
    <StoreProvider>
      <TodoStats />
      <TodoList />
    </StoreProvider>
  );
}

function TodoStats() {
  // ✅ 链式派生:stats 依赖 filteredTodos,filteredTodos 依赖 todos
  // 当切换 filter 时,filteredTodos 变 -> stats 变 -> 组件重渲染
  const stats = useStore((s) => s.stats);
  return (
    <div>
      总计: {stats.total} | 待办: {stats.active}
    </div>
  );
}

function TodoList() {
  // ✅ Selector 模式:只在 filteredTodos 变化时渲染
  const todos = useStore((s) => s.filteredTodos);
  const store = useStoreApi();

  return (
    <div>
      {todos.map((todo) => (
        <div key={todo.id} onClick={() => store.toggle(todo.id)}>
          {todo.text}
        </div>
      ))}
    </div>
  );
}

核心特性深度解析

1️⃣ 智能的计算属性 (@memo)

拒绝无效渲染。Zenith 的 @memo 类似于 MobX 的 computed,但完全基于不可变数据。

  • 链式派生:计算属性可以依赖其他计算属性,构建高效的数据流图。
  • 精准更新:如果计算结果的引用没有变化(Reference Equality),组件不会重渲染。
  • 显式依赖@memo((s) => [deps]) 让你清楚地知道数据流向,避免 MobX 的"魔法"黑盒。

2️⃣ 强制封装 (Force Encapsulation)

在团队协作中,状态管理最怕"随意修改"。Zustand 允许在组件中随意 setState,导致业务逻辑分散。

Zenith 强制你把逻辑写在 Store 内部:

// ✅ Good: UI 只负责调用意图
<button onClick={() => store.submitOrder(items)} />

// ❌ Bad: UI 无法直接修改 State(没有 setState 方法暴露)
// store.state.orders = ... // Error!

这使得重构变得极其简单(Refactor-friendly),查找引用(Find Usages)永远准确。

3️⃣ 灵活的生命周期管理 (StoreProvider)

拒绝状态污染,支持组件级状态隔离。

StoreProvider 赋予 Store 完整的 React 生命周期控制能力:

  • 🔄 组件级隔离:每个 <StoreProvider> 创建独立的 Store 实例,不同组件树之间状态完全隔离。
  • ♻️ 自动清理:组件卸载时 Store 自动销毁,避免内存泄漏。
  • 🧩 可复用组件:同一个 Store 可在多处使用,每个实例拥有独立状态,天然支持模块化。
// ✅ 推荐:通过 Provider 控制生命周期
function App() {
  return (
    <>
      <StoreProvider>
        <TodoList /> {/* 独立的 Store 实例 A */}
      </StoreProvider>
      <StoreProvider>
        <TodoList /> {/* 独立的 Store 实例 B */}
      </StoreProvider>
    </>
  );
}

// ⚠️ 也支持全局 Store,但不推荐(失去生命周期管理优势)
const globalStore = new TodoStore();

推荐始终使用 StoreProvider,即使是全局状态场景,也能获得更好的可测试性和组件隔离性。

4️⃣ 内置中间件架构

核心仅 1KB,但功能无限扩展。


📊 选型对比

| 特性 | Zenith | Zustand | MobX | Redux Toolkit | | :--- | :--- | :--- | :--- | :--- | | 核心范式 | Immutable Class | Functional | Mutable Class | Functional | | 计算属性 | ✅ @memo (链式) | ❌ (需手动) | ✅ computed | ⚠️ selector | | API 简洁性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | | 类型安全 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | | 团队规范性 | ✅ 强制封装 | ❌ 弱约束 | ⚠️ 弱约束 | ✅ 强约束 | | 撤销/重做 | ✅ Patches (极快) | ❌ | ❌ | ⚠️ 较重 | | 包体积 | ~1KB | ~1KB | ~16KB | ~20KB+ |


📖 更多文档


📦 安装

Zenith 依赖 immer 来处理不可变数据。

# npm
npm install @do-md/zenith immer

# pnpm
pnpm add @do-md/zenith immer

# yarn
yarn add @do-md/zenith immer

配置 tsconfig.json 以支持装饰器:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "useDefineForClassFields": false
  }
}

🎯 真实案例

domd — 基于 Zenith 构建的所见即所得 Markdown 编辑器。

  • ⚡️ 性能:处理 20,000+ 行文档丝滑流畅。
  • 🔙 撤销:基于 Zenith History 中间件的精确撤销重做。
  • 💾 内存:Immer Patches 极大降低了内存开销。

📄 License

MIT © Jayden Wang