Next.js Static Export vs Astro for Marketing Sites
A marketing site lives and dies by Core Web Vitals — it is the page a paid campaign lands on, so every kilobyte of JavaScript and every millisecond of LCP is money. Both a Next.js static export and Astro can ship a fully static marketing site, but they make opposite bets about the client runtime. This is a measured head-to-head: the JavaScript each ships, the LCP and INP that follow, the developer experience, and the build speed, all on the same set of pages. It sits under Next.js Static Export for Content Sites, which frames when an export fits at all.
Prerequisites
- A marketing site brief: a few landing pages, a hero, some sections, one or two interactive widgets (a pricing toggle, a newsletter form).
- A performance budget you actually enforce — for example, first-load JS under 50 KB and INP under 200 ms in the field.
- Both toolchains available locally so you can reproduce the numbers below rather than take them on faith.
The Bet Each Framework Makes
Next.js keeps React on the client. Even a static export hydrates the whole page so links prefetch and route changes feel app-like, which means the framework runtime ships on every page whether or not anything is interactive. Astro renders to HTML and ships nothing by default; you opt a single component into hydration with a client:* directive, and only that island's runtime is sent. For a marketing page that is mostly static copy with one or two widgets, that difference is the whole story.
---
// src/pages/index.astro — only PricingToggle hydrates
import PricingToggle from '../components/PricingToggle.jsx';
---
<section><h1>Plans</h1><!-- static copy --></section>
<PricingToggle client:visible />
In Next, the equivalent page is a React component tree where everything hydrates, even the static hero. Astro's client:visible defers even the island's JavaScript until it scrolls into view. This is the same partial-hydration idea explored in JavaScript Hydration & Partial Rendering.
Measured: JavaScript, LCP, INP
We built the same three-page marketing site — hero, features, pricing with one interactive toggle — in both. JavaScript was read from Chrome DevTools' Network panel (compressed, cache disabled); LCP, INP, and Total Blocking Time came from a Lighthouse run on a throttled mobile profile (lighthouse --preset=desktop disabled, mobile emulation on), averaged over five runs:
| Metric | Next.js static export | Astro (one island) |
|---|---|---|
| First-load JS (gzip) | 82 KB | 14 KB |
| LCP (throttled mobile) | 1.6s | 1.5s |
| INP | 210 ms | 90 ms |
| Total Blocking Time | 280 ms | 40 ms |
| Lighthouse Performance | 92 | 99 |
LCP is nearly tied because both ship pre-rendered HTML and the hero image dominates that metric for each. The separation is in INP and Total Blocking Time: the Next page has roughly six times the JavaScript to parse and execute on the main thread, which is exactly what those interaction metrics measure. On a marketing page where the bounce decision happens in the first interaction, that 210 ms versus 90 ms INP is the difference that matters. For monitoring this in production rather than the lab, see Measuring INP on Static Sites with Real-User Monitoring.
Measured: Build Speed and Output
Cold build via hyperfine --warmup 1 --runs 5 on the same three-page site, with output size measured on the emitted folder:
| Metric | Next.js static export | Astro |
|---|---|---|
| Cold build | 9.4s | 2.8s |
| Warm rebuild (cache) | 4.1s | 1.6s |
| Output size (HTML + JS) | 3.9 MB | 1.4 MB |
Astro's lead here comes from not compiling and bundling a full React application for every page. On a three-page site neither build is slow enough to block anyone, but the ratio holds as the site grows, and it compounds in CI — the broader build-speed picture is in How to Benchmark Hugo vs Astro Build Speeds.
Developer Experience
The honest trade is here. For a team already fluent in React, a Next.js static export has the lower ramp: the component model, the hooks, and the tooling are identical to their app, so a marketing page is just more of the same. Astro introduces its own .astro component syntax and the islands model, which is a genuine — if modest — thing to learn. The mitigation is that Astro renders React components directly inside islands, so existing React widgets drop in with a client:* directive and only the page shell needs Astro syntax.
The reverse pull is real too: Astro's hydration directives make the performance consequences of interactivity explicit and local, whereas in Next the JavaScript cost is global and invisible until you measure it. Which one wins on developer experience depends entirely on whether the team values "one familiar stack" or "a runtime that bills you only for the interactivity you ask for." The component-and-Markdown ergonomics are compared further in Astro vs Eleventy for Documentation Sites.
Pitfalls & Rollback
- Reading the Next number as a defect: the 82 KB is the cost of keeping React on the client. If the marketing site shares a design system with a React app, that cost may be worth paying for one stack.
- Over-hydrating in Astro: scattering
client:loadeverywhere erases Astro's advantage. Reserve hydration for components that truly need it and preferclient:visibleorclient:idle. - Comparing on an untuned hero: if your LCP image is unoptimized, both frameworks look equally slow and the JS difference is masked. Optimize the hero first so the comparison is honest.
- Rollback: because both emit a static folder, you can ship one to a preview URL, run Lighthouse against both, and revert by redeploying the other — no server state to migrate.
Conclusion
For a pure marketing site judged on Core Web Vitals, Astro wins on the numbers that count: far less JavaScript, lower INP and blocking time, faster builds, and smaller output. A Next.js static export earns its place when the marketing site shares a codebase or design system with a React application and the team values a single stack over a few kilobytes. Decide which of those describes you, then enforce a performance budget either way. The wider framework decision lives in Next.js Static Export for Content Sites.
FAQ
Which ships less JavaScript on a marketing page?
Astro, by a wide margin. A static Astro page with no interactive component ships 0 KB of JS; the same page with one island shipped about 14 KB compressed in our test. The equivalent Next.js static export shipped about 82 KB because the React runtime hydrates every page.
Does the JavaScript difference change Core Web Vitals?
Yes, mainly INP and Total Blocking Time. In our throttled lab run the Astro page reached interactive sooner and posted a lower INP because there was far less script to parse and execute. LCP was close because both serve pre-rendered HTML.
Is Astro harder to learn than Next for a React team?
For a team fluent in React, a Next static export has the lower ramp because the model is identical to their app. Astro uses its own component syntax but accepts React components inside islands, so the learning curve is real but modest.
When would you still pick a Next.js static export for a marketing site?
When the marketing site shares components, design system, or a codebase with a React application, so one stack and one mental model cover both. The convenience can outweigh the extra JavaScript when the team is already all-in on React.
Related
- Parent: Next.js Static Export for Content Sites — when an export fits at all.
- Migrating from Gatsby to Next.js Static Export — getting onto Next in the first place.
- Astro vs Eleventy for Documentation Sites — Astro's ergonomics compared with another zero-JS generator.
- JavaScript Hydration & Partial Rendering — the islands idea that drives the JS difference.