Benchmarks

Same page. Three libraries.

We built one settings page with Ermine, shadcn-vue and Nuxt UI, and measured what reached the browser and how fast it drew. Here are the numbers, how we got them, and what they do not show.

Shipped to the browser

JavaScript and CSS together, gzipped

Ermine
42.1 kB
shadcn-vue
109.3 kB2.6×
Nuxt UI
181.4 kB4.3×
No library
26.5 kB

First contentful paint

Cold load, processor slowed four times

Ermine
116 ms
shadcn-vue
176 ms1.5×
Nuxt UI
288 ms2.5×
No library
64 ms

Script time while loading

Cold load, processor slowed four times

Ermine
37 ms
shadcn-vue
93 ms2.5×
Nuxt UI
185 ms5.0×
No library
18 ms

Mount 1,000 rows

Five controls in each row, at full speed

Ermine
120 ms
shadcn-vue
394 ms3.3×
Nuxt UI
835 ms7.0×
No library
50 ms

Update 1,000 rows

Every checkbox and switch flipped at once

Ermine
90 ms
shadcn-vue
396 ms4.4×
Nuxt UI
591 ms6.5×
No library
6 ms

Memory with the rows mounted

JavaScript heap after garbage collection

Ermine
18.5 MB
shadcn-vue
70.4 MB3.8×
Nuxt UI
163.5 MB8.8×
No library
2.9 MB

Elements in the rows

DOM elements for 1,000 rows

Ermine
6,000
shadcn-vue
7,0001.2×
Nuxt UI
12,0002.0×
No library
6,000

Every number

MeasurementErmineshadcn-vueNuxt UINo library
Shipped to the browser
JavaScript and CSS together, gzipped
42.1 kB109.3 kB181.4 kB26.5 kB
JavaScript
Gzipped
37.9 kB99.8 kB156.5 kB26.5 kB
CSS
Gzipped
4.1 kB9.6 kB24.9 kB0.0 kB
First contentful paint
Cold load, processor slowed four times
116 ms176 ms288 ms64 ms
Script time while loading
Cold load, processor slowed four times
37 ms93 ms185 ms18 ms
Mount 1,000 rows
Five controls in each row, at full speed
120 ms394 ms835 ms50 ms
Update 1,000 rows
Every checkbox and switch flipped at once
90 ms396 ms591 ms6 ms
Memory with the rows mounted
JavaScript heap after garbage collection
18.5 MB70.4 MB163.5 MB2.9 MB
Elements in the rows
DOM elements for 1,000 rows
6,0007,00012,0006,000

"No library" is the same page in bare, unstyled HTML elements. It is the floor: what Vue itself costs before any component library.

How it was measured

  • The page. A settings form using 13 components: button, input, label, card, badge, checkbox, switch, tabs, accordion, dialog, select, dropdown menu and tooltip. The same content in each library, written the way that library's documentation shows.
  • The projects. Four fresh Vite 8 and Vue 3.5 projects from npm create vite, built for production with default settings. Ermine 0.3.0; shadcn-vue 2.8 · reka-ui 2.11 · Tailwind 4.3; Nuxt UI 4.11 · Tailwind 4.3.
  • Size. Every JavaScript and CSS file in the build, gzipped at the highest level.
  • Loading. A cold page in Chromium with the processor slowed four times, to stand in for a mid-range phone. The median of 15 loads.
  • Drawing. 1,000 rows, each with a badge, an input, a checkbox, a switch and a button, are mounted, then every checkbox and switch is flipped. Timed at full speed from the change until the browser has finished layout. The median of 10 runs, each on a new page. Runs varied by a few percent.
  • When. 13 October 2026, on one Apple laptop.

Why the gap

Ermine's checkbox, switch and input are native elements with styles. The other two build theirs on reka-ui, which gives each control its own JavaScript, its own memory and, in Nuxt UI's case, twice the elements. Neither choice is wrong; they buy different things. But it is most of the difference you see here.

What this does not show

  • It is one page, one browser and one machine. The pages were served from the same computer, so the paint times leave out the network. The sizes are the better guide to how a real visit loads.
  • The drawing test plays to Ermine's strength. It is all form controls and buttons. Opening dialogs, menus and selects was not timed, and there all three run comparable JavaScript.
  • CSS grows differently. Ermine's CSS grows with each component you add; all 141 together come to about 30 kB gzipped. Tailwind's utility CSS levels off, so on a large app the gap in CSS narrows.
  • Two choices favoured the others. Nuxt UI was built without a router, though its own setup guide adds one. The web font that shadcn-vue's default theme loads was removed.
  • Ermine has its own gap to close. Updating 1,000 rows takes far longer than the bare-element floor. That is on our list.

These libraries do more than this test measures, and are good at it. If size and speed are not what you are short of, choose on other grounds.