Svelte 团队成员开源新框架 Ripple,又一个想“改写前端”的框架?
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">作者 | Bruno Couriol </span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">译者 | 田橙 </span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Ripple 是一款全新的开源前端框架,融合了 React、SolidJS 和 Svelte 的理念,采用 Type 优先的设计思路,以组件为中心,并提供类似 JSX 的编译式语言、细粒度响应式机制以及作用域 CSS。该框架由 Svelte 核心维护者 Dominic Gannaway 打造,其响应式系统支持自动依赖追踪,无需虚拟 DOM 即可直接更新 DOM 节点,同时计划通过 AI 智能代理为开发者提供更高效的调试能力。</span></p><span style="color: green;"><span style="color: green;">import</span>{ <span style="color: green;">Button</span>} <span style="color: green;">from</span><span style="color: green;">./Button.ripple</span>; </span><span style="color: green;"><span style="color: green;">import</span>{ track } <span style="color: green;">from</span><span style="color: green;">ripple</span>; </span><span style="color: green;"><span style="color: green;">export</span>component <span style="color: green;">TodoList</span>({ todos, addTodo }: <span style="color: green;">Props</span>) { </span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">div</span></span><span style="color: green;"><span style="color: green;">class</span></span><span style="color: green;">=</span><span style="color: green;"><span style="color: green;">"container"</span></span><span style="color: green;">></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">h2</span></span><span style="color: green;">></span>{Todo List} <span style="color: green;"><span style="color: green;"><span style="color: green;">h2</span></span><span style="color: green;">></span></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">ul</span></span><span style="color: green;">></span></span><span style="color: green;">for (const todo of todos) {</span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">li</span></span><span style="color: green;">></span>{todo.text} <span style="color: green;"><span style="color: green;"><span style="color: green;">li</span></span><span style="color: green;">></span></span></span><span style="color: green;">}</span><span style="color: green;"><span style="color: green;"><span style="color: green;"><span style="color: green;">ul</span></span><span style="color: green;">></span></span></span><span style="color: green;">if (todos.length > 0) {</span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">p</span></span><span style="color: green;">></span>{todos.length}{" items"} <span style="color: green;"><span style="color: green;"><span style="color: green;">p</span></span><span style="color: green;">></span></span></span><span style="color: green;">}</span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">Button</span></span><span style="color: green;"><span style="color: green;">onClick</span></span><span style="color: green;">=</span><span style="color: green;"><span style="color: green;">{addTodo}</span></span><span style="color: green;"><span style="color: green;">label</span></span><span style="color: green;">=</span><span style="color: green;"><span style="color: green;">{</span></span><span style="color: green;">"</span><span style="color: green;"><span style="color: green;">Add</span></span><span style="color: green;"><span style="color: green;">Todo</span></span><span style="color: green;">"} /></span></span><span style="color: green;"><span style="color: green;"><span style="color: green;"><span style="color: green;">div</span></span><span style="color: green;">></span></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">style</span></span><span style="color: green;">></span></span><span style="color: green;"><span style="color: green;">.container</span>{ </span><span style="color: green;"><span style="color: green;">text-align</span>: center; </span><span style="color: green;"><span style="color: green;">font-family</span>: <span style="color: green;">"Arial"</span>, sans-serif; </span><span style="color: green;">}</span><span style="color: green;"><span style="color: green;"><span style="color: green;"><span style="color: green;">style</span></span><span style="color: green;">></span></span></span><span style="color: green;">}</span><span style="color: green;"><span style="color: green;">export</span>component <span style="color: green;">Counter</span>{ </span><span style="color: green;"><span style="color: green;">let</span>count = <span style="color: green;">track</span>( <span style="color: green;">0</span>); </span><span style="color: green;"><span style="color: green;">let</span>double = <span style="color: green;">track</span>( <span style="color: green;">=></span><span style="color: green;">@count</span>* <span style="color: green;">2</span>); </span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">div</span></span><span style="color: green;"><span style="color: green;">class</span></span><span style="color: green;">=</span><span style="color: green;"><span style="color: green;">counter</span></span><span style="color: green;">></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">h2</span></span><span style="color: green;">></span>{Counter} <span style="color: green;"><span style="color: green;"><span style="color: green;">h2</span></span><span style="color: green;">></span></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">p</span></span><span style="color: green;">></span>{"Count: "}{@count} <span style="color: green;"><span style="color: green;"><span style="color: green;">p</span></span><span style="color: green;">></span></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">p</span></span><span style="color: green;">></span>{"Double: "}{@double} <span style="color: green;"><span style="color: green;"><span style="color: green;">p</span></span><span style="color: green;">></span></span></span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">Button</span></span><span style="color: green;"><span style="color: green;">onClick</span></span><span style="color: green;">=</span><span style="color: green;"><span style="color: green;">{</span></span><span style="color: green;">=></span>@count++} label={Increment} /> </span><span style="color: green;"><span style="color: green;"><</span><span style="color: green;"><span style="color: green;">Button</span></span><span style="color: green;"><span style="color: green;">onClick</span></span><span style="color: green;">=</span><span style="color: green;"><span style="color: green;">{</span></span><span style="color: green;">=></span>@count = 0} label={Reset} /> </span><span style="color: green;"><span style="color: green;"><span style="color: green;"><span style="color: green;">div</span></span><span style="color: green;">></span></span></span><span style="color: green;">}</span>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">在 Ripple 中,开发者通过组件(例如 TodoList、Counter)来构建界面。组件本质是包含 DOM 表达式语句的函数,语法大量借鉴 Type 与 JSX,同时统一描述界面的标记结构(DOM)、样式(CSS)及交互行为。</span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">界面标记以原生语句形式直接表达,控制流逻辑(例如 if (todos.length > 0)、for (const todo of todos))可以自然穿插在 JSX 风格的结构中。样式默认作用域隔离,仅对当前组件生效。组件行为则由事件处理函数驱动,并依赖细粒度响应系统,使其能像 Svelte 一样精确更新真实 DOM,而非重新计算整个虚拟 DOM。</span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">track 原语用于定义独立响应式变量(如 count),其值通过 @ 运算符读取。计算型响应式变量(如 double)可通过 track( => @count * 2) 声明依赖关系。Ripple 的响应系统会确保这些变量始终保持同步。同时,它也保证 DOM 元素的状态随依赖变化自动更新。例如,点击按钮会让 count 自增,从而同步更新段落中的文本内容。</span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Gannaway 在 Twitter 上解释道:</span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Ripple 的响应式系统既不是虚拟 DOM,也不是 signals,而是基于细粒度、惰性求值的机制,它更多依赖编译器而非运行时,实现上述响应式能力。</span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Ripple 虽然不支持全局状态,但支持 Context,用于在组件间共享必要的应用状态。不过,Context 只能在其闭包范围内的组件使用,并且只能在组件上下文中读写,不能在事件处理器中进行读写操作。</span></p><span style="color: green;">import { Context } <span style="color: green;">from</span><span style="color: green;">ripple</span>; </span><span style="color: green;"><span style="color: green;">const</span>MyContext = <span style="color: green;">new</span>Context( <span style="color: green;">null</span>); </span><span style="color: green;"><span style="color: green;">component </span><span style="color: green;"><span style="color: green;">Child</span></span>{ </span><span style="color: green;"><span style="color: green;">// 在子组件中读取 Context</span></span><span style="color: green;"><span style="color: green;">const</span><span style="color: green;">value</span>= MyContext. <span style="color: green;">get</span>; </span><span style="color: green;">console.log( <span style="color: green;">value</span>); <span style="color: green;">// "Hello from context!"</span></span><span style="color: green;">}</span><span style="color: green;"><span style="color: green;">export component </span><span style="color: green;"><span style="color: green;">Parent</span></span>{ </span><span style="color: green;"><span style="color: green;">const</span><span style="color: green;">value</span>= MyContext. <span style="color: green;">get</span>; </span><span style="color: green;"><span style="color: green;">// 初次读取时尚未设置,回退到初始值 null</span></span><span style="color: green;">console.log( <span style="color: green;">value</span>); </span><span style="color: green;"><span style="color: green;">// 在父组件中设置 Context</span></span><span style="color: green;">MyContext. <span style="color: green;">set</span>( <span style="color: green;">"Hello from context!"</span>); </span><span style="color: green;">}</span>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Ripple 也允许以 effect 将副作用与状态变化关联:</span></p><span style="color: green;"><span style="color: green;">import</span>{ track, effect } <span style="color: green;">from</span><span style="color: green;">ripple</span>; </span><span style="color: green;"><span style="color: green;">export</span>component <span style="color: green;">App</span>{ <span style="color: green;">let</span>count = <span style="color: green;">track</span>( <span style="color: green;">0</span>); </span><span style="color: green;"><span style="color: green;">effect</span>( <span style="color: green;">=></span>{ </span><span style="color: green;"><span style="color: green;">console</span>. <span style="color: green;">log</span>( <span style="color: green;">@count</span>); }); </span><span style="color: green;"><span style="color: green;">@count</span>++}>{ <span style="color: green;">Increment</span>} } </span>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Ripple 的目标是为 Web 应用开发者带来更简单的思维模型和更好的开发体验。例如,默认不必使用 useMemo、CSS 自带作用域、没有额外抽象层隔离 DOM 与标记。该语言设计与编译器深度协作,使其能够更好地理解 Type 类型和响应式状态结构,为智能补全、错误检查和工具链打下基础。Ripple 团队也在探索在开发服务器中直接集成 AI 能力,实现主动式调试建议与问题诊断。</span></p>
<p style="font-size: 18px; line-height: 40px; text-align: left; margin-bottom: 30px;"><span style="color: green;">Ripple 由 Dominic Gannaway 创建,他曾在 Meta 参与 React Hooks 开发,创建富文本编辑器框架 Lexical,编写过轻量级框架 Inferno,并是 Svelte 5 核心团队成员。虽然 Ripple 已经存在数年,但最近才以 MIT 许可正式开源。目前框架仍处于早期阶段,欢迎社区贡献,并应遵循其贡献指南。</span><span style="color: green;">返回搜狐,查看更多</span></p>
页:
[1]