2026.10.30 · 4 min · react · vite · javascript · tooling
TanStack Redact: same React code, smaller engine.
import from "react" is a contract, not a file. TanStack Redact's build plugin points it at a runtime about a third the size, so your unchanged app ships less JavaScript, at the cost of React's time slicing. What it swaps, what it saves, and what breaks. As of 2026.10.
import { useState } from "react" looks like it names one fixed package. It doesn't. It names a module, and your bundler decides what that resolves to. TanStack Redact (0.2.0, released 2026.10.26) uses exactly that: a build plugin points react at a smaller runtime, and your components, hooks and imports stay as they are.
Watch the 60-second version on Instagram.
The import is a contract
Redact replaces React and React DOM in the browser. You add it to the build config and nothing else changes. Its Vite plugin redirects react, react-dom, the JSX runtimes, react-dom/client, scheduler, use-sync-external-store and the compiler runtime to Redact.
import { defineConfig } from 'vite'
import { redact } from '@tanstack/redact/vite'
export default defineConfig({
plugins: [redact()], // preset: 'full' by default
})Install it with pnpm add @tanstack/redact. Version 0.2.0 ships stable browser integrations for TanStack Start, Vite, Vinext and Next.js (both the App and Pages Router).
The bars are to scale. The runtime alone, gzipped: React 19.3.0 is 69,162 bytes and Redact on its default Vite setup is 23,311, which is 66.3% smaller, about 3x. You'll see "about 4x" in some third-party summaries. The README doesn't say that.
It's not a new framework. You still write React. Only the engine under the import changes. It's the same idea as aliasing a module in your bundler, and if you read my post on TanStack Start server functions, it's another case of the build deciding what code actually ships.
What it saves
All client JavaScript and CSS for the same small demo app, gzipped:
| Framework | Saving |
|---|---|
| Vite | 68.3 KB → 20.1 KB (−70.5%) |
| TanStack Start | −43.0% |
| Vinext | −28.5% |
| Next.js | 175.6 KB → 139.9 KB (−20.4%) |
Read the 70.5% as "a small Vite demo app". The saving depends on the framework and on your app, and a real app saves less. Smaller also doesn't mean faster: the benchmark didn't measure rendering or hydration speed.
There are two presets. full, the default, turns on every optional feature except view transitions. nano turns them all off, and the Vite app drops to 12.6 KB. You can also switch off single flags such as context, suspense, memo, portal, hydration and classComponents, but code that uses a disabled feature breaks: with context: false, every context read returns its default.
What it costs: time slicing
Redact renders synchronously. There is no time slicing and no interruptible render, so a heavy render can delay input.
The timings in the figure are illustrative. React can split a long render and handle the click between slices. Redact runs the same work as one block, and the click is handled when it ends.
The rest of the compatibility list:
useTransitionanduseDeferredValuework, but without priority scheduling.<Profiler>'s callback is a no-op, and StrictMode doesn't double-invoke.- Not implemented:
ReactDOM.render,hydrate,findDOMNode, Fizz prerender/resume, and Server Components/Flight. Those stay on real React on the server. A legacyReactDOM.renderapp breaks. - Not verified by the maintainers: Safari, Firefox, and animation in production.
nanochanges behaviour quietly. No context and no Suspense fallback, which matters if one of your dependencies relies on them.
On a client project I'd try Redact on the bundle first and then click through the busiest screen we have before trusting the smaller number.
The short version
import from "react"names a module. The bundler decides which code it resolves to.- Redact's plugin resolves it to a runtime of 23,311 bytes gzipped, against React 19.3.0's 69,162.
- A small Vite demo app went from 68.3 KB to 20.1 KB. Next.js saved 20.4%. Real apps save less.
- Rendering is synchronous: no time slicing, so a heavy render can delay a click.
- No
ReactDOM.render, Server Components stay on real React on the server, and Safari and Firefox are unverified.
Sources: TanStack, Introducing TanStack Redact · Redact docs, Vite plugin · TanStack/redact README · Redact docs, Feature Flags · Redact docs, Compatibility