Profile
Back to NewsBack
GitHub Trending 9 min
Reader Mode
octanejs/octane: React’s programming model, compiled. The successor to Inferno.

octanejs/octane: React’s programming model, compiled. The successor to Inferno.

15 hours ago

Octane

CI status: beta npm version License: MIT

Octane is a fast JavaScript UI framework, and the successor to Inferno. You write components with the React API you already know, and a compiler turns them into direct DOM code before they ship. No virtual DOM, no rules-of-hooks bookkeeping, and no dependency arrays to maintain by hand.

Created by Dominic Gannaway, who also created Inferno and has worked on React, Lexical, Ripple, and Svelte.

import { useState } from 'octane';

export function Counter() @{ const [count, setCount] = useState(0);

<button onClick={() => setCount(count + 1)}> {'Count: ' + count} </button> }

Why Octane

Your React knowledge transfers. useState, useEffect, memo, context, portals, Suspense, transitions: same API, same mental model, checked case by case against a large behavioral suite. React-derived coverage is tracked in the generated parity report rather than inferred from the size of the suite.

Standard JSX works, .tsrx gives you more. Paste a component from the React docs into a .tsx file and it runs. Or author in .tsrx, the spiritual successor to JSX, and get template directives (@if, @for, @switch, @try) that compile to keyed fast paths, plus an @{ … } shorthand that puts setup next to the output. Mix both dialects in one app and import across the boundary. TSRX Syntax for VS Code adds syntax highlighting, diagnostics, navigation, and completions for .tsrx files.

Write the closure, not its dependency list. Omit the array from useEffect, useMemo, useCallback, and friends, and the compiler derives it from what the closure actually captures, including stable setters, dispatchers, refs, and state getters. This is the no-bookkeeping DX people associate with signal frameworks, without leaving the hooks model. Explicit arrays still mean exactly what they mean in React.

No rules of hooks. Hooks are tracked by call site, not call order, so a hook can live inside an if or after an early return. The one rule left is enforced for you: a hook in a plain JS loop is a compile error, because every iteration would share a single call-site slot. Use the keyed @for directive instead, where each item gets its own hook state.

The platform, not a reimplementation of it. Real delegated DOM events, controlled form components on native events (React's value/checked semantics, with onInput per edit and native onChange on commit), and refs as plain props (ref={cb}, ref={obj}, even ref={[a, b]}). No synthetic layer second-guessing the browser.

No virtual DOM. Components re-render like React, but a compiled render path and an LIS-based keyed reconciler keep the runtime overhead minimal.

Octane's native renderer is deliberately narrow where React has grown wide: no class components, no Server Components, no synthetic event system. Those are choices, not gaps, and they are written down in Differences from React.

Also in the box

  • Editable state that follows its source. useLinkedState resets or adjusts
local state as soon as an input changes, with no effect and no state update during render.
  • Promises in render are safe. No cache() wrapper: creations feeding
use() are memoized at their declarations, including local .then chains. Independent requests start together, one suspension per stratum, and descendant fetch trees prefetch while an ancestor is still suspended.
  • Streaming SSR and byte-stable hydration, with out-of-order Suspense
flushing over Node or web streams, or buffered and static rendering when you want it.
  • Deferred hydration. keeps server HTML visible but inert until
it is worth activating, and splits its children into their own chunk by default.
  • Behavior-only roots for externally owned DOM. Attach abortable behavior
and delegated native events to server-rendered or independently streamed markup without rendering it or taking reconciliation ownership.
  • React interoperability in both directions. Keep real React components
inside Octane with ReactCompat, or add Octane components to a React app with OctaneCompat. Both are available from octane/react.
  • Optional immutable render snapshots. Add "use strong" to one module, or
enable Strong mode for an application, to assert pure renders, catch detectable violations, and let production memoization condition every user-authored render call shape on its witnessed inputs.
  • class / className composes clsx-style everywhere: strings, arrays,
objects, and nesting, at every apply site. exposes $class plus one key per class for class={theme.dark} and