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 #4 in JavaScript SEO#285 in Technical SEO#381 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 hydrationTurning HTML, CSS, and JavaScript into the final visual page and DOM. 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 renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. 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. CrawlabilityCrawlability is how well search engine crawlers can discover, access, and fetch a site's pages. A crawlability issue is any technical condition — blocked access, broken links, server failures, or bloated URL inventory — that stops pages from reaching the index., indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed., and measured Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. 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 SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. 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-hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers. app, the server sends finished HTML — great for first paint and for crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. — 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 TimeTotal Blocking Time — the sum of the blocking portion (time above 50 ms) of every long task between First Contentful Paint and Time to Interactive. It's a lab-recommended metric and the lab proxy for INP, not a Core Web Vital. (TBTTotal Blocking Time — the sum of the blocking portion (time above 50 ms) of every long task between First Contentful Paint and Time to Interactive. It's a lab-recommended metric and the lab proxy for INP, not a Core Web Vital.) in the lab and poor Interaction to Next PaintInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good. (INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good.) 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 loadingLazy loading defers loading of off-screen or non-critical resources — usually images and iframes — until they're about to enter the viewport. The native way to do it is the loading=\"lazy\" HTML attribute, which needs no JavaScript. 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 crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor. 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 VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. — 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 SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. 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.

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 crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. need (that’s the whole JavaScript SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. 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 descriptionThe meta description is an HTML head tag — `<meta name=\"description\" content=\"…\">` — that suggests a short summary of the page for the search snippet. It's not a Google ranking factor, and Google rewrites it the majority of the time, but a good one can still lift click-through., 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 outputSearch ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance.’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 renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. for how Google’s pipeline handles this generally.

Where to go next

Each framework has its own dedicated deep dive:

  • Qwik SEOQwik SEO is the practice of optimizing sites built with Qwik, a JavaScript framework whose 'resumability' model serializes app state into HTML so the browser never has to hydrate. Content is in the HTML by default, so crawling, indexing, and Core Web Vitals are all structurally strong. — 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 SEOSolidJS SEO is the set of practices for making SolidJS apps crawlable, indexable, and fast. Bare SolidJS renders client-side (an empty HTML shell), so SEO depends on using SolidStart for SSR or SSG to put real content and metadata in the initial HTML. — 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 SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. cluster alongside the framework-specific guides for React, Vue, Angular, Next.js, Nuxt, Svelte, and Astro. For the metric side, see Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data.; for how Google sees rendered content, see renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM..

Add an expert note

Pin an expert quote

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