Skip to content

Bundle size ​

Gzipped size of the code an app pays for each Formhaus entry and for other form libraries.

Size at 1.0 ​

CI fails a pull request that goes over these limits in scripts/check-bundle-size.mjs.

App importsLimitMeasured
Every export of @formhaus/core27 KB24.3 KB
Every export of @formhaus/core and @formhaus/react33 KB29.5 KB
Every export of @formhaus/core and @formhaus/vue36 KB32.9 KB
FormEngine from @formhaus/core19 KB17.1 KB
useFormEngine from @formhaus/react or @formhaus/vue, with core20 KB17.7 KB

Rendering paths ​

The entry you import sets the size. React and Vue are not counted.

EntryYou writeReactVue
FormEngineAll markup, in any framework. The engine does state, conditions, validation, steps and a basic structure check17.1 KB17.1 KB
useFormEngineAll markup. The hook gives the visible fields of the step, values, errors, the current step, setValue, next, back and submit17.7 KB17.7 KB
HeadlessFormRendererA component for each field type, actions and progress. The renderer does steps, field order, conditions, focus and the error summary25.9 KB27.7 KB
FormRendererNothing. Built-in fields, actions and progress; replace some types through components29.3 KB32.6 KB

These cost the same on any path, and only when imported:

ImportAdds
checkDefinition() with warnings and hints, for an editor, CI or AI generation5.8 KB
@formhaus/core/cloud3.1 KB
@formhaus/core/i18n3.8 KB
@formhaus/core/fix9.2 KB
Engine warnings in development0 KB in production

Measured on main on 2026-10-20 with node scripts/compare-bundle-size.mjs. 1 KB is 1024 bytes.

useFormEngine: you render everything.

tsx
const engine = useFormEngine(definition);

return engine.visibleFields.map((field) => (
  <input key={field.key} value={String(engine.values[field.key] ?? '')} onChange={(event) => engine.setValue(field.key, event.target.value)} />
));

HeadlessFormRenderer: you register a component for each field type.

tsx
<HeadlessFormRenderer
  definition={definition}
  components={{ text: MyInput, email: MyInput, select: MySelect }}
  actionsComponent={MyFormActions}
  progressComponent={MyStepProgress}
  onSubmit={handleSubmit}
/>

FormRenderer: the built-in fields, with some types replaced.

tsx
<FormRenderer definition={definition} components={{ phone: MyPhoneInput }} onSubmit={handleSubmit} />

Vue examples and the full props are in Choose a renderer.

Other libraries ​

LibrarygzipState and validationRenderingMulti-stepSame validation on the serverJSON definitions
react-hook-form 7.90.011.5 KBYesNoNoWith a schema resolver shared with the serverNo
@formhaus/core FormEngine only17.1 KBYesNoYesvalidateSubmission()Yes
formik 2.4.9 + yup 1.7.125.7 KBYesNoNoThe Yup schema runs on the serverNo
@formhaus/core + @formhaus/react29.5 KBYesYesYesvalidateSubmission()Yes
@formkit/vue 2.1.230.1 KBYesYesPlugin in @formkit/addons, not countedNoFormKit schema
@formhaus/core + @formhaus/vue32.9 KBYesYesYesvalidateSubmission()Yes
react-jsonschema-form 6.11.0 (@rjsf/core + @rjsf/validator-ajv8)125.3 KBYesYesNoAJV runs the JSON Schema on the serverJSON Schema and UI schema
SurveyJS 3.2.1 (survey-core + survey-react-ui)409.3 KBYesYesYesonServerValidateQuestions calls your server checkYes

Formhaus built from main, the other libraries installed from npm at the versions above, all measured on 2026-10-20 and bundled with esbuild 0.28.2 as in Method.

Imports ​

LibraryEntry
react-hook-formuseForm
formik + yupuseFormik from formik, object and string from yup
@formkit/vueplugin, defaultConfig, FormKit
react-jsonschema-formForm from @rjsf/core, validator from @rjsf/validator-ajv8
SurveyJSModel from survey-core, Survey from survey-react-ui
Formhaus engineFormEngine from @formhaus/core
Formhaus pathsuseFormEngine, HeadlessFormRenderer or FormRenderer from @formhaus/react or @formhaus/vue
Formhaus subpathsFormEngine with checkDefinition, or with every export of /cloud, /i18n or /fix, minus FormEngine alone
Formhaus ReactEvery export of @formhaus/react
Formhaus VueEvery export of @formhaus/vue

Method ​

Each entry is bundled with esbuild:

  • bundle, minify, format: 'esm'
  • process.env.NODE_ENV set to "production"
  • react, react-dom and vue are external
  • CSS is not counted
  • the output is gzipped at level 9

Dependencies and peer dependencies such as @rjsf/utils are in the bundle. Other libraries are installed from npm at the versions above into a temporary directory. Formhaus is built from the repository.

The same method runs in CI in scripts/check-bundle-size.mjs.

Reproduce ​

sh
pnpm install
pnpm build
node scripts/compare-bundle-size.mjs