前端圈有个老矛盾——喜欢 React 的 JSX 写法,又羡慕 Vue 的细粒度响应式更新。Rue.js(发音 /ruː/,中文名"后悔药.js")就是给这个矛盾开的方子:JSX/TSX 语法不变,底层却用 Rust 写的响应式系统驱动 DOM 编译,还通过 WebAssembly 把运行时扩展塞进浏览器。
语法兼容:React 写法 + Vue 响应式
Rue.js 的核心承诺很简单——你继续写熟悉的 JSX 组件,但数据变更不再触发整棵虚拟 DOM 树的 diff,而是像 Vue 3 的 Vapor 模式那样,精确更新受影响的 DOM 节点。
这意味着:
- 组件结构:函数组件 + JSX,和 React 函数组件几乎一致
- 状态管理:响应式变量声明方式接近 Vue 的
ref/reactive,但写在 JSX 函数体内 - 更新粒度:变量变化时只更新绑定的 DOM 属性,不走虚拟 DOM diff
业务层用 TypeScript,框架层的关键路径用 Rust/WASM 实现——这是 Rue.js 性能故事的根基。
Block / Vapor 渲染路径
Rue.js 默认走 Block 渲染路径(类似 Vue 3 Vapor 模式的思路)。编译阶段把模板拆成静态 Block 和动态 Block,运行时只对动态部分做响应式绑定,静态部分直接生成 DOM 操作序列,跳过对比环节。
好处很直接:
- 首次渲染快——静态部分预编译成 DOM 创建指令,没有虚拟 DOM 构建开销
- 更新快——只有响应式变量绑定的节点会被触碰,其余 DOM 完全不动
- 内存省——不需要维护整棵虚拟 DOM 树的 JavaScript 对象
Rust + WASM:响应式系统的底层引擎
Rue.js 的响应式系统用 Rust 实现,编译成 WebAssembly 在浏览器中运行。这带来两个实际收益:
- 依赖收集与调度:Rust 侧的响应式图计算比纯 JS 实现更快,尤其在组件数量多、依赖关系复杂时差距明显
- 运行时体积:WASM 二进制比等效 JS 代码更紧凑,框架运行时整体更小
路由模块同样基于 Rust/WASM 扩展,路径匹配和守卫逻辑在 WASM 侧执行,减少 JS 主线程负担。
实践:写一个 Rue.js 组件
下面是一个典型的 Rue.js 组件写法——声明响应式状态、绑定 JSX、处理事件。语法对 React 开发者来说几乎零学习成本,但更新机制完全不同。
注:Rue.js 目前仍在早期阶段,以下示例基于框架公开的设计理念编写,具体 API 可能随版本调整,请以官方文档为准。
// Counter.tsx — Rue.js 组件示例
import { ref, computed } from "@ruejs/reactivity";
import { defineComponent } from "@ruejs/core";
export const Counter = defineComponent(() => {
// 响应式状态声明,类似 Vue 的 ref
const count = ref(0);
const doubled = computed(() => count.value * 2);
// JSX 事件绑定,React 开发者直接上手
const increment = () => {
count.value += 1;
};
const decrement = () => {
count.value -= 1;
};
return (
<div class="counter-card">
<h2>后悔药计数器</h2>
<p>当前值:{count.value}</p>
<p>双倍值:{doubled.value}</p>
<div class="btn-group">
<button onClick={decrement}>−1</button>
<button onClick={increment}>+1</button>
</div>
</div>
);
});
关键差异解读:
ref(0)创建响应式变量,修改.value时只更新绑定了{count.value}的那个<p>节点,不会重渲染整个组件computed自动追踪依赖——count变了,doubled立刻重算,对应的<p>也同步更新- JSX 结构完全保留,不需要像 Vue 那样写
<template>块
路由配置
Rue.js 的路由同样在 JSX 体系内声明,匹配逻辑由 Rust/WASM 模块执行:
// app.tsx — 路由配置示例
import { createRouter, Route } from "@ruejs/router";
import { Counter } from "./Counter";
import { Home } from "./Home";
const router = createRouter([
<Route path="/" component={Home} />,
<Route path="/counter" component={Counter} />,
]);
export const App = () => {
return (
<div id="app">
<nav>
<a href="/">首页</a>
<a href="/counter">计数器</a>
</nav>
<RouterView router={router} />
</div>
);
};
项目初始化
假设 Rue.js 提供了 CLI 脚手架(具体命令以官方发布为准):
# 创建项目
npx create-rue-app my-project --template tsx
# 进入目录并启动开发服务器
cd my-project
npm run dev
# 构建生产版本(含 WASM 编译)
npm run build
npm run build 时,Rust 侧的响应式模块会被编译成 WASM 并内联到产物中,不需要额外部署 .wasm 文件。
选型考量:什么时候值得试
Rue.js 目前是早期项目,选型时需要清醒评估:
适合尝试的场景:
- 团队主力是 React JSX 习惯,但对虚拟 DOM diff 性能不满意
- 中小型项目需要轻量框架,不想引入 React + 状态库的完整全家桶
- 对 WASM 有兴趣,想在真实项目中验证 Rust/WASM 在前端的收益
暂时观望的场景:
- 大型生产项目——生态(UI 库、工具链、社区方案)还不成熟
- 强依赖 React 生态特定库(Redux、React Query 等)——兼容层尚未完备
- 团队全员 Vue 习惯且无迁移意愿——此时直接用 Vue 3 Vapor 模式更稳
一个简单的选型检查清单:
| 条件 | 建议 |
|---|---|
| JSX 是团队刚需 | ✅ 值得关注 |
| 响应式细粒度更新是痛点 | ✅ 核心卖点 |
| 项目可接受早期框架风险 | ✅ 可以试 |
| 需要 SSR/大量第三方 React 库 | ⏸️ 等生态补齐 |
| 团队完全不用 JSX | ⏸️ 收益有限 |
后悔药这个名字挺有意思——给那些"当初选了 React 又想要 Vue 响应式"的开发者一粒回头药。框架本身的设计思路清晰,Rust/WASM 在响应式层的介入方向也合理。等 API 稳定、工具链完善后,它会是一个值得认真评估的轻量选项。