Nuxt vs Qwik: Hydration, Resumability, and What Actually Moved Our Numbers
Vue's meta-framework against resumability. We ship neither — but the two decisions behind our Lighthouse 100s are identical in both, and one cost us 1.67s.
Nuxt is the Vue meta-framework: server rendering, file routing, and a large module ecosystem, with hydration after the server HTML lands. Qwik is its own framework whose headline feature is resumability — it serialises state into the HTML and never hydrates, downloading event handlers only on interaction. Nuxt is the safer default; Qwik is the bet on a different execution model.
We run Next.js 16.2.9 and React 19.2.4 here, and we have never shipped a Nuxt or a Qwik build, so nothing below is a head-to-head benchmark — anyone presenting one for your app is guessing. What this storefront can offer is a measured account of which decisions actually moved its numbers across 27 routes, 111 products and 381 blog posts, because both of these frameworks leave those same decisions to you.
The real axes
| Nuxt | Qwik | |
|---|---|---|
| Base library | Vue 3 | Its own (JSX syntax, not React) |
| Meta-framework | Nuxt is it | Qwik City |
| Client startup | Hydrates after SSR | Resumes — no hydration pass |
| Code loading | Route- and component-level chunks | Per-handler, lazy by default |
| Static generation | Mature (nuxt generate), hybrid route rules | Supported via adapters |
| Ecosystem | Large module library, Vue's whole ecosystem | Small; qwik-react bridges React components |
| Learning curve | Low if you know Vue | New model: $ boundaries, serialisation rules |
| Risk profile | Established, widely deployed | Smaller community, fewer answers when stuck |
For the honest comparison, put Qwik City beside Nuxt rather than bare Qwik — Qwik City is to Qwik what Nuxt is to Vue. Comparing a framework to a meta-framework is how these posts usually go wrong.
Hydration vs resumability, and what it is worth
Nuxt renders on the server, ships the component code, and re-executes it in the browser to attach listeners. Qwik serialises the application state into the HTML and resumes: no re-execution, and a handler is fetched when you first interact with the thing it belongs to. That is a genuinely novel idea, and the saving is real in one specific case — a page with a lot of interactive components.
The question nobody asks first is how much of your page is interactive at all. On this storefront, most of it is not. Of 92 component files under src/components, 26 carry "use client", and the interactive ones cluster on the authenticated routes — the pricing accordion, the gallery carousel, the download menu, the forms. A marketing page with one mobile-menu toggle has almost no hydration cost to eliminate, so resumability competes against a number that is already near zero.
That is the trap in framework benchmarks: they measure a demo whose shape is nothing like a content site's. If your product is a dashboard with fifty live widgets, resumability is addressing your actual bottleneck. If it is a storefront or a marketing site, the wins are elsewhere — and this is where we have numbers.
What actually moved our numbers
Desktop Lighthouse is 100 for performance, accessibility and SEO across all eight main pages; mobile performance runs 89–99 with accessibility and SEO at 100. Neither figure came from the framework's rendering model. They came from two decisions that Nuxt and Qwik would both have left to us.
First: how much is prerendered. Every page on this site is static HTML built ahead of time. Three files carry a generateStaticParams, and they turn dynamic segments into individually prerendered pages — 110 available product pages, 381 blog posts, 7 category hubs. Nuxt does this well with nuxt generate and hybrid route rules; Qwik City does it through its static adapter. Both will also happily server-render everything per request if you do not ask. The framework is not the variable; whether you prerendered is.
Second: images, which no framework solves for you by default. The catalog had grown to 111 products and 892 JPEGs totalling 117 MB. A product cover is painted at 530×330 in a card, and the source JPEG is 2120px wide — about 255 KiB delivered to show roughly 33 KiB worth of pixels. Nuxt has @nuxt/image; Qwik has its own image helpers; Next.js has next/image. We deliberately use none of them, because every one of those optimises at request time and bills for it.
Instead the variants are built once, committed, and served as plain static files:
// src/lib/imageVariants.ts
/** Card thumbnails: 530px CSS wide at DPR 2, so 1060 covers every display. */
export const CARD_VARIANT_WIDTH = 1060;
/** Full-bleed 16:9 slides on the detail page, matching the markup's width. */
export const VIEW_VARIANT_WIDTH = 1600;
const RASTER = /\.(?:jpe?g|png|webp)$/i;
function variant(src: string, suffix: string): string {
return RASTER.test(src) ? src.replace(RASTER, `-${suffix}.webp`) : src;
}
/** Card-sized cover — product grids, the related rail, dashboard thumbnails. */
export function cardImage(src: string): string {
return variant(src, "card");
}
scripts/images/build-variants.ts generates them; npm test fails if a product is missing one. The source JPEG stays full-size because it has a second job — it is the og:image and the Product schema's image, where a large universally-decodable file is correct. Net effect: public/images went 117 MB → 93 MB while adding 110 card variants, and there is no request-time optimizer on any of the three frameworks' bills.
This is the kind of work that decides a content site's Core Web Vitals, and it is identical in Nuxt, in Qwik and here.
The defect that cost 1.67 seconds
One measured example of how little the framework had to do with it. The LCP image on /templates was loading="lazy", so the browser could not discover it until layout ran — 1.67s of load delay on a page whose rendering model was never the problem.
The fix was a prop, not a framework feature: TemplateCard takes priority, the first card of a page-opening grid sets it, every other card stays lazy. Nuxt and Qwik would both have let us ship exactly that bug, and the fix in either is the same one line. We wrote up the whole pass in Next.js image optimization without next/image.
Choosing between them
Pick Nuxt if your team knows Vue, you want a module for most problems, you are hiring, or the project has to be maintainable by whoever inherits it. Its static generation is mature and its documentation assumes you want a content site. For most teams most of the time this is the answer, and "boring" is a feature.
Pick Qwik if your page genuinely has many interactive components and you have measured hydration as the bottleneck — not assumed it. You should also be comfortable with its constraints: state that crosses a $ boundary has to be serialisable, which is a real design discipline rather than a detail, and the answer to an unusual problem may not exist on the internet yet.
Pick neither on benchmark screenshots. A framework's demo page tells you about its demo page. The axis that decided our numbers — static output plus build-time assets — is available in both.
If you are weighing these against the React side of the fence, Qwik vs Next.js takes the resumability argument apart against this repo's client/server split, and Next.js vs Nuxt covers the Vue/React decision directly.
Common mistakes
| Mistake | Why it misleads | Better question |
|---|---|---|
| Comparing bare Qwik to Nuxt | Nuxt is a meta-framework; Qwik City is its counterpart | Compare Qwik City to Nuxt |
| Treating resumability as free speed | It removes hydration cost you may not have | How many interactive components does the page have? |
| Benchmarking a TodoMVC | Demo shape ≠ product shape | Measure your own heaviest route |
| Assuming the framework optimises images | All three hand you request-time optimisers, or nothing | Can you build variants at deploy time? |
| Shipping SSR by default | Both frameworks will render per request happily | Which routes could be fully static? |
| Choosing on GitHub stars | Says nothing about your bottleneck | Can you hire for it, and debug it at 2am? |
| Ignoring the LCP image | The biggest single win on a content page | Is the first image eager and correctly sized? |
Frequently asked questions
Is Qwik faster than Nuxt? On a page with many interactive components, Qwik's model does less work at startup by design. On a mostly-static marketing or content page, both ship HTML and the difference is dominated by images, fonts and third-party scripts — which is what our own 89–99 mobile scores turned on, not the rendering model.
Can I use Vue components in Qwik, or React components?
Not Vue. Qwik provides qwik-react for reusing React components, which is the migration path people actually take. Vue components belong in Nuxt.
Which is better for SEO? Both server-render, so both are indexable; search engines see HTML either way. The things that moved our SEO scores to 100 were per-page metadata, canonicals, JSON-LD and honest sitemap dates — all framework-agnostic. See programmatic SEO with Next.js for the mechanics.
Is Qwik production-ready? It is used in production, but the ecosystem and the volume of community answers are much smaller than Nuxt's. That is a staffing and support risk more than a technical one — weigh it as such rather than dismissing the framework.
Templates in this post
ASoc Till is a point-of-sale marketing site with a live register preview and app-store CTAs, ASoc Timbre is an AI voice-generator landing page with a voice-sample player and a languages showcase, and ASoc Uptime is a web-hosting site with a domain-search widget and tiered pricing. All three are statically prerendered with build-time WebP covers — the two decisions above, already made.
Browse the full sets: Next.js landing page templates, Tailwind landing page templates.
