Next-Gen JavaScript Frameworks

How Qwik's resumability and SolidJS's fine-grained reactivity reduce browser JavaScript startup work — and why neither mechanism by itself guarantees crawlability, indexing, or Core Web Vitals.

First published: Jun 26, 2026 · Last updated: Jul 18, 2026 · Advanced
demand #6 in JavaScript SEO#310 in Technical SEO#426 on the site

"Next-gen" is an editorial label used here for Qwik and SolidJS, not a standardized web-platform category. Qwik uses resumability — it serializes listeners, component boundaries, and state into the HTML during SSR/SSG so the browser can resume specific work instead of replaying a full hydration bootstrap. That's not zero JavaScript: Qwikloader (a small bootstrap script) still runs on load, registers listeners, and lazy-loads handler code (QRLs) on interaction. SolidJS uses fine-grained reactivity — signals and no virtual DOM mean targeted DOM updates without a component re-render — and it still hydrates, just not the same mechanism as resumability. Neither the framework's reactivity model nor its meta-framework (QwikCity, SolidStart) guarantees a route's HTML, metadata, status code, or measured Core Web Vitals; those depend on the rendering mode and implementation you actually ship. This hub maps the two mechanisms and points to the dedicated deep dives.

Evidence for this claim Qwik documents resumability and fine-grained lazy loading as core execution strategies. Scope: Qwik architecture; real transferred and executed JavaScript depends on the application. Confidence: high · Verified: Qwik documentation: Resumability Evidence for this claim Solid uses fine-grained reactive primitives and supports server rendering through its framework tooling. Scope: Solid/SolidStart architecture; SEO and performance depend on rendering configuration and application code. Confidence: high · Verified: Solid documentation

TL;DR — “Next-gen frameworks” is this article’s own editorial grouping for Qwik and SolidJS, not a standardized category — both target JavaScript execution cost in the browser, by different mechanisms. Qwik uses resumability — the app pauses on the server and serializes listeners, component boundaries, and state into the HTML so the browser can resume specific work instead of replaying a full hydration bootstrap; a small bootstrap script (Qwikloader) still runs on load and lazy-loads handler code on interaction, so this is not literally zero JavaScript. SolidJS uses fine-grained reactivity — signals and no virtual DOM, so updates are surgical — and it still hydrates (not resumability; that’s the myth to bust). Framework reactivity is a separate concern from meta-framework rendering mode: QwikCity and SolidStart can emit server-rendered HTML, but SolidStart also supports pure client-side rendering, and neither ships a router or metadata library by default. Crawlability, indexing, and measured Core Web Vitals depend on the rendering mode and implementation you actually ship — no framework or reactivity model guarantees them.

The root cause they’re attacking

Open the JavaScript SEO hub and the failure modes are about whether Google can see your content. That’s a rendering mode question — SSR, SSG, or CSR — and QwikCity and SolidStart both support server-rendered or statically generated output, though neither forces it: pick CSR and you’re back to an empty-shell SPA regardless of the framework underneath. What Qwik and SolidJS actually change is the other half of the story: the cost of the JavaScript that runs after the HTML arrives.

In a typical SSR-plus-hydration app, the server sends finished HTML — great for first paint and for crawlers — but then the framework downloads its component code and re-executes it in the browser to attach event handlers and rebuild its internal state. That hydration pass is pure overhead from the user’s point of view: the page looks ready but isn’t interactive, and the main thread is blocked. This is the single biggest contributor to high Total Blocking Time (TBT) in the lab and poor Interaction to Next Paint (INP) in the field.

Both Qwik and SolidJS exist to shrink or eliminate that pass. They take different routes.

Qwik: resumability (no hydration — but not zero JS either)

Qwik’s headline idea is resumability, and Qwik (currently a v2 beta) is the framework whose reactivity model I’m calling out here — QwikCity is the separate meta-framework layer, covered below. The framework runs on the server, renders the HTML, and then serializes everything the app needs to continue — state, event listeners, the component tree, the place in execution — directly into the HTML. When the page loads in the browser, Qwik doesn’t re-run your components to wake them up. It resumes from where the server left off, instead of replaying a full hydration bootstrap.

That’s genuinely different from hydration, but it is not zero JavaScript. A small bootstrap script, Qwikloader (documented at about 1kb minified, executing in under 5ms on mobile per Qwik’s own docs), still runs on every page load. It:

  • registers a single global event listener instead of attaching one listener per interactive element,
  • reads the serialized on:click="./chunk.js#handler_symbol"-style attributes Qwik wrote into the HTML (these are QRLs — Qwik Resource Locators),
  • and, when an event actually fires, resolves the matching QRL and lazy-loads the specific handler chunk before running it.

The practical consequences:

  • Startup JS is small and roughly constant, not zero. Qwikloader’s own cost doesn’t grow with your app size, and no full-app hydration pass runs — but Qwikloader itself is real, executing JavaScript. Don’t describe this as “zero JS on load”; describe it as “a small, constant-size bootstrap instead of a hydration pass that scales with app size.”
  • Lazy loading down to the handler. Application code loads only when an interaction actually happens, which is what Qwik’s authors mean by “HTML-first.”
  • QwikCity is Qwik’s meta-framework — file-based routing, data loaders, actions, endpoints — the full-stack layer that produces server-rendered or static, resumable HTML. Qwik’s resumability doesn’t by itself decide a route’s status code, metadata, or whether it’s server-rendered at all; QwikCity’s routing and rendering configuration does.

Where resumability breaks in practice

Resumability has real constraints worth knowing before you rely on it (per Qwik’s current serialization and state docs):

  • Serialization boundaries. Code inside a $(...) boundary can only capture serializable values — primitives, const-bound serializable data, and a few built-in types Qwik knows how to serialize (including promises). A custom class instance or other unsupported capture passes static analysis but fails at runtime when Qwik tries to serialize it — a silent-until-shipped failure mode worth testing for.
  • noSerialize() values don’t survive resumption. Anything explicitly marked non-serializable is set to undefined after the client resumes from SSR/SSG state, and has to be reinitialized on the client — typically inside useVisibleTask$().
  • useVisibleTask$ is an eager, browser-only escape hatch. Qwik’s own docs call it a last resort: it runs only in the browser, after initial render, and “eagerly executes code on the client” — by default gated on visibility via an intersection observer, but immediately on load if you set { strategy: 'document-ready' }. Overusing it reintroduces the startup cost resumability is designed to avoid.

For SEO specifically: whether a QwikCity route’s server output includes your content and <a href> links in the initial HTML is a rendering-mode and routing question, not something resumability guarantees on its own — check the actual response, not just the framework choice. See crawling for what Google needs there. The resumability mechanism’s realistic upside is on the runtime side: less startup JavaScript to block the main thread, which is a factor in Core Web Vitals — not a guarantee of a particular INP or TBT number.

SolidJS: fine-grained reactivity (smarter hydration — not resumability)

SolidJS attacks the same cost from a different angle, and — same caveat as above — Solid the reactivity engine is a separate thing from SolidStart the meta-framework. Solid’s core idea is fine-grained reactivity built on signals, and it has no virtual DOM.

  • Signals, not re-renders. In React, a state change re-runs the component function and diffs a virtual DOM to figure out what changed. In Solid, a component function runs once; signals (getter/setter pairs created with createSignal) and subscribers (like createEffect) track dependencies directly, so when a signal changes, only the code actually subscribed to it reruns — no component re-execution, no virtual-DOM diff. This is why Solid consistently sits at or near the top of framework benchmarks (the js-framework-benchmark suite) on update-heavy workloads — see that benchmark directly for current numbers rather than a fixed claim here, since benchmark results shift across framework versions.
  • It still hydrates — SolidJS is not a resumability framework. Its server renderer produces HTML and the client hydrates it — this is a different mechanism from Qwik’s resumability, not a variant of it. Fine-grained reactivity and no virtual DOM mean Solid’s hydration pass has less work to reconstruct than a typical VDOM framework’s, but “hydration is cheaper here” is a mechanism-level statement, not a fixed number — actual hydration cost still depends on how much interactive code a given route ships. Do not describe SolidJS as “resumable.”
  • SolidStart is Solid’s meta-framework — routing, server functions, and deployment presets, the SolidStart equivalent of QwikCity / Next.js. Current SolidStart docs (v1.0, labeled beta, last updated 2026-04-28) list three rendering modes you choose per app: client-side rendering (CSR), server-side rendering (SSR — sync, async, or streaming), and static site generation (SSG). Solid’s fine-grained reactivity runs the same way regardless of which mode you pick; the rendering mode is what determines whether a route’s initial HTML contains your content at all. SolidStart’s own docs are explicit that it does not bundle a router or metadata library by default — you add one yourself, which means metadata handling isn’t automatic just because you’re using SolidStart.

For SEO: whether a SolidStart route’s content and links land in the initial HTML depends on which of those three rendering modes it uses — CSR alone produces an empty shell like any SPA, same as picking CSR anywhere else. SSR or SSG modes put content in the HTML the way JavaScript SEO requires. The CWV upside is mechanism-level: a smaller runtime and fine-grained updates reduce the work hydration has to do — it doesn’t set a specific TBT or INP number on its own.

The distinction, stated plainly

This is the accuracy spine of the whole topic, so be precise:

  • Qwik = resumability. No hydration bootstrap. A small, roughly constant-size bootstrap script (Qwikloader) runs on load; application code lazy-loads on interaction. Resumes from serialized server state.
  • SolidJS = fine-grained reactivity + hydration. No virtual DOM, dependency- tracked signals, but it does hydrate. It is not resumability.

Both reduce browser JavaScript work relative to a typical VDOM-plus-full-hydration app, but by different mechanisms, and neither eliminates browser JavaScript entirely. Conflating “resumability” with “zero JS,” or treating SolidJS as resumable, are the two most common mistakes about this pairing.

An adjacent comparison boundary: Astro islands

Worth naming since it comes up in the same conversations: Astro’s islands architecture is a third mechanism, not a variant of either one above. Astro ships plain server-rendered HTML by default and lets you opt specific components into client-side hydration (“islands”) via client directives — most of the page never ships component JavaScript at all. That’s a useful comparison boundary for “how much of the page needs to be interactive,” but it isn’t resumability (Qwik) or fine-grained-reactivity hydration (Solid) — it’s partial hydration of an otherwise static page. Qwik’s own docs explicitly distinguish resumability from partial hydration for this reason.

Evidence for this claim Astro islands can provide a useful comparison boundary because they opt selected components into client execution, but islands/partial hydration are not the same mechanism as Qwik resumability or Solid fine-grained reactivity. Scope: comparison boundary Confidence: high · Verified: Islands architecture

How they compare to the established frameworks

ReactVueAngularSolidJSQwik
Reactivity modelVDOM + re-renderVDOM + reactivityZone.js / signals (v16+)Signals, no VDOMSignals, no VDOM
Browser work on load (SSR)HydrationHydrationHydrationHydration (less to reconstruct)Resumption (Qwikloader bootstrap, no full hydration)
Startup JS costScales with appScales with appScales with appScales with app’s interactive surfaceSmall bootstrap; app code lazy-loads on interaction
Content in server/static HTMLDepends on rendering mode (Next/Remix)Depends on rendering mode (Nuxt)Depends on rendering mode (@angular/ssr)Depends on rendering mode (SolidStart: CSR/SSR/SSG)Depends on rendering mode (QwikCity)
Meta-frameworkNext.js / RemixNuxtAngular SSRSolidStartQwikCity

The established frameworks are not bad for SEO by default — with the right rendering mode, their meta-frameworks all put content into the HTML, which is what crawlers need (that’s the whole JavaScript SEO story), and the same is true of SolidStart and QwikCity. What differs between the columns above is the mechanism behind browser startup cost, not a guaranteed outcome — measure TBT/INP on your actual routes rather than assuming a framework choice settles it.

A caveat worth keeping honest: React, Vue, and Angular are all moving toward signals and lighter hydration themselves (Angular’s signals, React Server Components, Vue’s Vapor mode). Version and roadmap specifics change quickly enough that any snapshot here would go stale — check each framework’s current docs before citing a specific capability.

Validating any of this on your own routes

Don’t take a framework’s reputation as the answer for a specific route. Check, per route:

  • Status code and initial HTML — fetch the URL directly (not through the browser’s rendered DOM) and confirm your content, links, and metadata are actually present.
  • Streamed output, if the rendering mode streams — confirm the full content arrives, not just a shell plus a loading state.
  • Metadata and links — title, meta description, canonical, and <a href> targets, since neither resumability nor fine-grained reactivity manages these for you.
  • Serialized state size (Qwik) — large serialized state inflates the HTML payload even though it avoids a hydration bootstrap.
  • Initial loader/runtime JavaScript actually executed — measure what Qwikloader or Solid’s runtime does on load, not just what the docs claim.
  • Prefetched and interaction-triggered requests — watch the network panel for what loads on click versus what loaded up front.
  • Browser-only tasks (useVisibleTask$ and equivalents) — confirm they’re not firing eagerly on every load.
  • Behavior when JavaScript fails or is blocked — does the route degrade to something usable, or break entirely?
  • Representative crawler-rendered output — Search Console’s URL Inspection tool or an equivalent renderer, not just View Source, since some content only appears after rendering.

This is the same validation discipline any JavaScript-rendered site needs; see rendering for how Google’s pipeline handles this generally.

Where to go next

Each framework has its own dedicated deep dive:

  • Qwik SEO — resumability in practice, QwikCity routing and SSR, getting metadata right, the useDocumentHead pattern, lazy-loading boundaries, and how resumability shows up in field CWV.
  • SolidJS SEO — signals and fine-grained reactivity, SolidStart SSR and streaming, why it’s not resumable, meta-tag management, and benchmark context.

Both sit under the JavaScript SEO cluster alongside the framework-specific guides for React, Vue, Angular, Next.js, Nuxt, Svelte, and Astro. For the metric side, see Core Web Vitals; for how Google sees rendered content, see rendering.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin an expert quote first.