Migrating My Blog from Next.js to Astro
Nick Tenebruso
About a year ago, I decided to switch my blog from Next.js to a new framework called Astro. Here are the reasons why I decided to make the switch.
Comparison
Foremost, I’ll give a brief overview of both Next.js and Astro. Next.js is a web framework built around React, which aims to provide SSR (server side rendering) and SSG (server side generation) out of the box. The basic idea of Next.js is that React code will be generated or served as static HTML, then it will get “hydrated” to be interactive using Javascript through shipping the React runtime. Astro is a web framework that lets you build components with a variety of different libraries, including React, Angular, Svelte, and Vue (although most code is written using Astro’s component language). However, unlike Next.js, Astro focuses on shipping as little JavaScript as possible, meaning that these components will not ship any JavaScript or hydrate unless specifically designed to be interactive.
Why No Hydration is Better
Shipping zero JavaScript is definitely not better for every use case, but for a static blog like the one I have, I found that it was far too overkill to ship the entire React runtime only for a tiny amount of interactivity (which is pretty much only the theme switcher). And while the current Astro site does ship JavaScript, its compiled bundle is far smaller than the Next.js version as all interactivity is written in vanilla JS or Svelte (which does not require a runtime and compiles to vanilla JavaScript).
Performance
The end-user performance of both frameworks turned out to be almost exactly the same for my use case. However, when taking into account the size of the bundled JavaScript, Astro has the clear edge. Next.js transfers 694 kB of bundled JavaScript to the client, while Astro transfers only 7.9 kB.
Astro lighthouse report Next.js lighthouse reportDeveloper Experience
While Next.js is my absolute favorite framework for building React apps, Astro’s developer experience has been amazing because it allows developers to build components in whatever framework they choose. Additionally, features like Markdown to HTML support are built into Astro, while I had to manually write features like a Markdown parser in Next.js. Here’s an example of the code I needed to write in Next.js vs Astro to get a list of blog posts.
Next.js:
export async function getAllPosts() {
const files = fs
.readdirSync(postsPath)
.filter((file) => path.extname(file) == ".mdx");
return Promise.all(
files.map(async (slug) => {
const post = fs.readFileSync(path.join(postsPath, slug), "utf-8");
const { data } = matter(post);
return { ...data, slug: slug.replace(".mdx", "") };
})
);
}
Astro:
import { format } from "date-fns";
const posts = (await Astro.glob("./posts/*.mdx")).sort((a, b) => {
return (
new Date(b.frontmatter.publishedAt).getTime() -
new Date(a.frontmatter.publishedAt).getTime()
);
});
As you can see, Astro’s code is much more straightforward, and did not require manually reading and parsing data from the filesystem. Instead, this functionality is abstracted to the Astro.glob
API.
Conclusion
In conclusion, I’ve found Astro to be a great framework for building my blog, as it focuses on server side generation while shipping as little Javascript as possible. Overall, I would definitely recommend it to anyone building a static website or blog.