smolter
Guides

Bundle size and tree shaking

Choose basic routing or the full data flow. Measure the exports your application actually uses.

Compatibility

ReactAvailable in this renderer's browser integration.
React SSRAvailable to this renderer's SSR integration; browser event handlers run after hydration.
PreactAvailable in this renderer's browser integration.
Preact SSRAvailable to this renderer's SSR integration; browser event handlers run after hydration.

Your features. Your footprint.

Start with navigation. Add only what your app needs.

Framework

Combined browser bundle

4,124 bytes gzip
Brotli
3,683 B
Minified
11,069 B

Measured together, including shared code. Production Vite fixture; framework runtime and your app code excluded. Your build may differ.

Unchecked prefetch modes are removed by Smolter’s Vite plugin when usage is statically known. Dynamic spreads retain possible modes. Other features follow named-import tree shaking.

Choose your features

The selector measures each valid combination as one production Vite bundle. Paths, links and history are always included. Server rendering requires data routing; speculative data requires data routing and a prefetch mode. Choose React or Preact to see gzip, Brotli and minified bytes. Framework runtimes and application code are excluded. Shared code means feature sizes cannot be added together. These Vite measurements differ from the esbuild/Terser comparison table below.

Routing only

Use createRouter with named imports from @kasperrt/smolter/preact for navigation only. Its data engine is absent from the bundle. Use createDataRouter for loaders/actions, fetchers and revalidation. React offers both factories through /react.

React routing only: 1825 B gzip
Preact routing only: 1807 B gzip
React common routing/data: 3936 B gzip
Preact common routing/data: 3916 B gzip
wouter routing subset: 2854 B gzip
wouter-preact routing subset: 2211 B gzip
React Router declarative routing: 12882 B gzip
React Router data routing: 29780 B gzip
React Router complete entry: 60994 B gzip
React complete entry: 5591 B gzip
Preact complete entry: 6185 B gzip
React + server transport: 7301 B gzip
Preact + server transport: 7906 B gzip
React + client + document: 10440 B gzip
React + client + document + lazy routes: 10731 B gzip
Preact + client + document: 11072 B gzip
Preact + client + document + lazy routes: 11357 B gzip

Measured tiers

Sizes below are generated from the current build. Routing-only uses createRouter; common routing/data uses createDataRouter. Complete entries retain both factories and every other export. The comparable wouter subset retains Router, Route, Switch, Link, useParams and useLocation. Framework runtimes are excluded. Shared code makes rows non-additive.

Optional prefetch capabilities

Smolter’s Vite plugin selects prefetch implementations from typed JSX, spreads and createElement calls. Intent-only applications omit the observer; viewport-only applications omit intent handlers; unused data prefetch omits its cache. Unions retain all possible modes. Plain Link means intent. Opaque inputs and component-value escapes retain capabilities conservatively. Source-level analysis can retain code from unused source files; it does not claim whole-program runtime inference. Without the plugin, all implementations remain available. Existing entrypoint tables use ordinary bundling without this Vite selection; the command below measures production Vite fixtures separately.

pnpm build
node scripts/prefetch-size.mjs

Full applications

Full applications use createDataRouter. The SSR and file-router client helpers already select it. SSR applications additionally use /preact/client and /preact/document; lazy file routes use /preact/lazy-route. Server rendering and the Vite plugin stay in their dedicated subpaths. Complete client-entry measurements include the optional deployment watcher. Named imports that do not use watchDeployment remove it; the routing and data entrypoints do not import it.

Comparison exports and versions

Measured against wouter and wouter-preact 3.13.0, and react-router 8.4.0. React Router has no dedicated Preact export: its React API is measured here, not a Preact compatibility build. These APIs differ in capabilities; sizes are not claims of feature equivalence. All measurements use the same production minification and gzip settings.

// React Router declarative subset
BrowserRouter, Routes, Route, Link, useParams, useLocation

// React Router data subset
createBrowserRouter, RouterProvider, Link, Form, useLoaderData,
useActionData, useParams, useLocation, useRevalidator, useFetcher

// Smolter routing subset
createRouter, defineRoute, RouterProvider, Routes, Link, useParams, useLocation

// Smolter data subset
createDataRouter, defineRoute, RouterProvider, Routes, Link, Form,
useRouter, useLoaderData, useActionData, useParams, useLocation,
useRevalidator, useFetcher

Reproduce

pnpm size refreshes both the named-export comparison table (esbuild, Terser, gzip level 9) and the feature selector (production Vite with Smolter’s plugin, gzip level 9, Brotli quality 11). React, React DOM and Preact are external. The selector builds every valid combination, including its small Link fixture, rather than adding separate compressed totals. Your application imports and build configuration can produce different results.

pnpm size
pnpm size -- --breakdown