Skip to main content
ASoc
Comparison

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.

The ASoc Team8 min read

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

NuxtQwik
Base libraryVue 3Its own (JSX syntax, not React)
Meta-frameworkNuxt is itQwik City
Client startupHydrates after SSRResumes — no hydration pass
Code loadingRoute- and component-level chunksPer-handler, lazy by default
Static generationMature (nuxt generate), hybrid route rulesSupported via adapters
EcosystemLarge module library, Vue's whole ecosystemSmall; qwik-react bridges React components
Learning curveLow if you know VueNew model: $ boundaries, serialisation rules
Risk profileEstablished, widely deployedSmaller 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

MistakeWhy it misleadsBetter question
Comparing bare Qwik to NuxtNuxt is a meta-framework; Qwik City is its counterpartCompare Qwik City to Nuxt
Treating resumability as free speedIt removes hydration cost you may not haveHow many interactive components does the page have?
Benchmarking a TodoMVCDemo shape ≠ product shapeMeasure your own heaviest route
Assuming the framework optimises imagesAll three hand you request-time optimisers, or nothingCan you build variants at deploy time?
Shipping SSR by defaultBoth frameworks will render per request happilyWhich routes could be fully static?
Choosing on GitHub starsSays nothing about your bottleneckCan you hire for it, and debug it at 2am?
Ignoring the LCP imageThe biggest single win on a content pageIs 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.

Keep reading

Comparison7 min read

One-Time Payment vs Subscription: What the Webhook Handler Has to Know

Our entitlement engine is 75 lines with two status states; our LemonSqueezy webhook recognizes two event names. That's not a shortcut — it's the real cost gap between the two pricing models.

Read more
Comparison8 min read

Playwright vs Vitest: Why This Repo Runs Both for Unrelated Jobs

Vitest is a committed dependency gating 305 tests on every push. Playwright is deliberately not a dependency at all — installed ad hoc for a script that runs a few times a year.

Read more
Comparison9 min read

Qwik vs. Next.js: Resumability vs. Not Shipping the Component

Qwik ships near-zero JS through resumability; this site's RSC split already does that for 9 of 10 home-page sections. Where the real cost still lands: one accordion.

Read more