Astro vs. Next.js: Why I Prefer Astro For Static Sites
I've been using the Astro framework to create mostly static websites (like this one) for a while, dating back to around its 1.0 release. During this time, I've also spent months experimenting with the much more popular Next.js framework, which is used by companies like Spotify, OpenAI, Nike, and more.
But I keep returning to Astro.
I have yet to find a better framework for static or content-heavy websites. In this post, I'll explain why I prefer Astro (version 4.5) and how it outperforms Next.js (version 14.1) for this use case.
Zero JS, unless you add it
I want a scalable framework.
Something that easily allows me to add interactivity to a page when needed but also lets me scale down to a primarily static site like landing pages, blogs, and portfolios.
I've written about how adding client-side JavaScript to a site is one of the fastest ways to slow it down. To that end, a framework shouldn't make assumptions about how much JavaScript your site needs. You should make that call, not the framework.
Because of its client-side router and dependence on React.js (among other things), Next.js will load a minimum of 87 KB of JavaScript (after compression) — even if your page is blank. How much JavaScript does Astro load for that same page?
Zero. Nada. Zilch.
Astro will only load JS that you tell it to load. And that's what I expect.
If you want to add more interactivity to a page, Astro lets you use vanilla JS, a UI library like React, Preact, Vue, Svelte, HTMX, or even a combination of any of those. It's UI-agnostic and defers that decision to you. In contrast, Next.js is a React-first framework that advertises itself as "The React Framework for the Web."
Server first
Astro and Next.js differ in how they handle routing. Next.js
encourages you to use their
<Link>
component when linking to other pages. It uses client-side JavaScript
to re-render the part of the page that has changed, avoiding a full
page refresh. By default, this component can make navigating a website
feel very snappy because it also prefetches the page the link
points to when the link enters the viewport.
On the other hand, Astro doesn't provide any special link component,
instead relying on the standard old <a href="">
tag to leverage the
browser's innate ability to perform navigation. With this method, the
browser performs a full page refresh, rendering the HTML on the
server. Astro doesn't prefetch any link by default, but a simple
configuration change
will enable it. With this change, you can closely mimic Next.js's fast
page navigations.
So which approach is better?
For simple or content-heavy sites that don't require the app-like functionality that client-side navigation offers, I prefer Astro's approach:
- By using client-side navigation, Next.js must re-implement
navigation features in JavaScript that the standard anchor tag and
browser already provide for free. These include essential
accessibility features like a
route announcer
to notify users with accessibility issues that the page has loaded.
And have you ever noticed the loading indicator browsers show you
after you click a standard link that tells you the page is loading?
Well, with client-side navigation, you are responsible for adding
that behavior. Otherwise, a user who clicks a link while on a slow
connection won't be able to tell that anything is happening. In
addition to frustrating your users, this lack of feedback may also
negatively affect your
Interaction to Next Paint
score. Next.js does let you add a
loading.js
file you can use to implement a loading indicator, but why go through the trouble of reinventing these critical features when HTML and browsers already provide robust solutions? - On a related note, relying on the browser to perform something as critical as navigation is safer than relying on a JavaScript framework. Even at the time of this writing, Next.js has a long-standing bug that causes the browser to not scroll to the top of the page after navigation in certain situations. Meanwhile, browsers have spent decades perfecting idiosyncrasies like this.
- Offloading HTML rendering to the server can make your website more responsive to users on low-powered devices like cheap cell phones that can struggle to run heavy JavaScript. Mobile users often comprise most of a website's traffic, so this demographic should be considered unless your analytics suggest otherwise.
Even if you find your website needing client-side navigation down the road, Astro allows you to imitate this behavior through View transitions.
Content first
Try adding a blog to an Astro and Next.js site or compare the Astro docs with the Next.js docs on the topic, and you'll quickly realize that content is much more of a first-class citizen in Astro.
After trying both out, I found that Astro has better out-of-the-box support for the following:
- Defining and querying content. Seriously, Astro's content collections are fantastic.
- Using and validating frontmatter
- Adding image references to frontmatter, such as a cover photo
- Syntax highlighting
- Data formats like JSON and YAML. Useful for referential data, like author information or related content, that you don't want to store in a database but that belongs on each piece of content.
Don't get me wrong — you can workaround these issues in Next.js if you're motivated enough. But it made me feel like I was jumping through hoops that the framework should provide more help with.
Conclusion
In summary, I love using Astro because it takes advantage of what is already built on the web platform, provides an excellent developer experience when authoring content, and doesn't load any JavaScript by default. If you're creating a mostly static site, I highly recommend it.