Describe the bug
@tanstack/form-core unconditionally imports and uses @tanstack/devtools-event-client in production builds. The devtools event client (7.5 KB unminified) is a hard dependency in form-core's package.json and is imported at the top level of FormApi.ts and utils.ts with no process.env.NODE_ENV guard, no import.meta.env.DEV check, and no dead-code-elimination hint.
This means every app using @tanstack/react-form ships the full devtools plugin system to users, regardless of whether TanStack Devtools is installed or used.
What ships in production
Analyzing a Vite production build, the useForm chunk contains:
- The full
EventClient class from @tanstack/devtools-event-client (~7.5 KB source, ~4 KB minified)
tanstack-devtools-global event listeners
tanstack-connect / tanstack-connect-success connection handshake logic
- Retry loops with
setInterval for reconnection attempts
CustomEvent dispatching infrastructure
🌴 [tanstack-devtools:form-devtools-plugin] debug log strings (minified but present)
@tanstack/pacer-lite's liteThrottle (~0.5 KB) used solely to throttle devtools state broadcasting
In our production bundle, this accounts for ~11.6 KB of dev-only code in the useForm chunk (39 KB total).
Root cause
In packages/form-core/src/EventClient.ts:
import { EventClient } from '@tanstack/devtools-event-client'
class FormEventClient extends EventClient {
constructor() {
super({ pluginId: 'form-devtools', reconnectEveryMs: 1000 })
}
}
export const formEventClient = new FormEventClient()
This singleton is instantiated unconditionally at module load time. It's then imported and used throughout FormApi.ts (mount, update, reset, submit) and utils.ts (throttleFormState).
Because the formEventClient singleton has side effects at instantiation (it creates internal state, sets up connection properties), bundlers cannot tree-shake it even though form-core declares "sideEffects": false.
Related issues
Expected behavior
The devtools event client infrastructure should not be included in production builds. Possible approaches:
- Guard with
process.env.NODE_ENV !== 'production' — wrap devtools imports and usage so bundlers can dead-code-eliminate the entire devtools path in production builds.
- Lazy/conditional initialization — only instantiate the
FormEventClient when devtools are actually connected (e.g., when globalThis.__TANSTACK_EVENT_TARGET__ exists).
- Move devtools integration to the devtools package — instead of form-core importing the event client, have
@tanstack/react-devtools hook into form instances externally (similar to how React DevTools hooks into React).
Your minimal, reproducible example
npm create vite@latest my-app -- --template react-ts
npm install @tanstack/react-form
- Use
useForm in any component
npx vite build && npx vite-bundle-visualizer
- Observe
@tanstack/devtools-event-client and @tanstack/pacer-lite in the production bundle
Steps to reproduce
- Install
@tanstack/react-form@1.28.6 (or latest 1.29.0)
- Build for production with Vite (or any bundler)
- Inspect the output chunks — the devtools event client is present
Platform
- macOS
- Node 24.x
- Vite 7.3.1
- @tanstack/react-form 1.28.6
- @tanstack/form-core 1.28.6
- @tanstack/devtools-event-client 0.4.3
TanStack Form adapter
react-form
TanStack Form version
1.28.6
TypeScript version
5.6.3
Additional context
The @tanstack/pacer-lite dependency (hard dep of form-core) is also only used for throttleFormState which exclusively serves the devtools state broadcasting. If the devtools code were properly gated, pacer-lite could also be eliminated from production bundles.
Describe the bug
@tanstack/form-coreunconditionally imports and uses@tanstack/devtools-event-clientin production builds. The devtools event client (7.5 KB unminified) is a hard dependency inform-core'spackage.jsonand is imported at the top level ofFormApi.tsandutils.tswith noprocess.env.NODE_ENVguard, noimport.meta.env.DEVcheck, and no dead-code-elimination hint.This means every app using
@tanstack/react-formships the full devtools plugin system to users, regardless of whether TanStack Devtools is installed or used.What ships in production
Analyzing a Vite production build, the
useFormchunk contains:EventClientclass from@tanstack/devtools-event-client(~7.5 KB source, ~4 KB minified)tanstack-devtools-globalevent listenerstanstack-connect/tanstack-connect-successconnection handshake logicsetIntervalfor reconnection attemptsCustomEventdispatching infrastructure🌴 [tanstack-devtools:form-devtools-plugin]debug log strings (minified but present)@tanstack/pacer-lite'sliteThrottle(~0.5 KB) used solely to throttle devtools state broadcastingIn our production bundle, this accounts for ~11.6 KB of dev-only code in the
useFormchunk (39 KB total).Root cause
In
packages/form-core/src/EventClient.ts:This singleton is instantiated unconditionally at module load time. It's then imported and used throughout
FormApi.ts(mount, update, reset, submit) andutils.ts(throttleFormState).Because the
formEventClientsingleton has side effects at instantiation (it creates internal state, sets up connection properties), bundlers cannot tree-shake it even thoughform-coredeclares"sideEffects": false.Related issues
@tanstack/react-devtoolscomponents via@tanstack/devtools-vite, but that only strips the devtools UI — it does not address the event client baked intoform-coreitself.CustomEventusage in the event client, but the fix (bumping the event client version) did not address the production bundling concern.Expected behavior
The devtools event client infrastructure should not be included in production builds. Possible approaches:
process.env.NODE_ENV !== 'production'— wrap devtools imports and usage so bundlers can dead-code-eliminate the entire devtools path in production builds.FormEventClientwhen devtools are actually connected (e.g., whenglobalThis.__TANSTACK_EVENT_TARGET__exists).@tanstack/react-devtoolshook into form instances externally (similar to how React DevTools hooks into React).Your minimal, reproducible example
npm create vite@latest my-app -- --template react-tsnpm install @tanstack/react-formuseFormin any componentnpx vite build && npx vite-bundle-visualizer@tanstack/devtools-event-clientand@tanstack/pacer-litein the production bundleSteps to reproduce
@tanstack/react-form@1.28.6(or latest 1.29.0)Platform
TanStack Form adapter
react-form
TanStack Form version
1.28.6
TypeScript version
5.6.3
Additional context
The
@tanstack/pacer-litedependency (hard dep of form-core) is also only used forthrottleFormStatewhich exclusively serves the devtools state broadcasting. If the devtools code were properly gated,pacer-litecould also be eliminated from production bundles.