How I Migrated From Wordpress to Astro: Boosted Pagespeed Scores to 100% and Cut 100% Hosting cost
![How I Migrated From Wordpress to Astro: Boosted Pagespeed Scores to 100% and Cut 100% Hosting cost](/_astro/wordpress-to-astro@2x.D-cx6BdG_Z1xq01B.webp)
I want to share my story of how I migrated this blog from WordPress to static website with Astro.js, and boosted its performance.
I have been blogging on WordPress since 2015. I went through many customization and optimization efforts, from adding countless plugins to developing my own WordPress theme. I went on hiatus from 2016 to 2020, blogging again in 2020, and went on hiatus again in 2021.
In May this year, I decided to write on my blog again. But this time, I want to blog on a Static website (JAMStack) because I don’t want to spend time managing Hosting and optimizing a WordPress blog. I want to focus more on content.
I know the static website is faster, but it also requires more technical skills to build, which luckily, I have it.
Blogging with Static Site Generator
Blogging with Static Site Generator is different from conventional blogging in WordPress. You have to decide how you write and store your content.
1. Store contents in the blog repository as Markdown files
Almost every Static Site Generator supports this. You store your content in a directory inside your blog repository in GitHub as .md
or .mdx
files. Upon running the build script for your project, this content will be parsed into HTML pages.
You will have to write your content in your code editor. When you are done, you just need to commit and push it to your GitHub repository to publish it.
Your blog codes and contents are stored in one place.
2. Using Headless CMS or External API
You store your blog contents separately from the codes. You can use headless CMS like Strapi, Directus, PayloadCMS, or even use your WordPress CMS. You have to pay for the service or self-hosted your CMS.
In your blog project, you will need to fetch the contents from headless CMS API or WordPress Rest API. You also need to set a build trigger every time you update new content.
Your blog codes and contents are stored separately.
In my case, I chose the #1 method. Other than a cheaper option, it is also convenient for me to write directly in Markdown format in VSCode, a tool that I use every day.
I dont need to log in to CMS to write, and when I have to cross-post my article to dev.to or hashnode, I can just copy-paste it :smile:
Before Astro
Before migrating my blog to the JAMStack website, I researched the popular Static Site generation libraries, such as Gatsby, Next.js SSG, Docusaurus, and Astro. I chose Docusaurus because it has all the built-in features for static site generation.
Migrated to Docusaurus
I know about Docusaurus when I need a documentation website for my open source project paradise-ui.com. Then, I found out that it has a built-in blog feature and can be switched to blog-only mode.
So, I chose it to save my time. I don’t want to build it from scratch. I customized the design using Docusaurus swizzle feature and Tailwindcss. The new design is the same design you see right now.
Exporting WordPress contents to Markdown files
Docusaurus detects contents in .md
and .mdx
files. So, I need to migrate my WordPress posts to .md
files.
I used this open source WordPress export to markdown. To use it, you need to clone the project and run it locally.
You also have to export all your WordPress content first from the WordPress admin.
It will generate a .xml
file. Place this .xml
file in the root directory of wordpress-export-to-markdown
project, and rename it to export.xml
.
Run the wordpress-export-to-markdown
project as per documentation. It will generate your WordPress content in the form of .md
files.
~~
So far, my experience with Docusaurus is positive. It increased my blog’s overall page speed because it’s a static website, but never reached 100% performance.
The Docusaurus is a bit bloated with unused javascripts. But, I can understand that because it was originally built for a Documentation website, not a blog.
Migrated to Astro
When I came back to blogging, I had to catch up on the latest trends in web development. I heard a lot about Astro. I was a bit skeptical, because ‘It’s another javascript framework’.
But I was curious because everyone who uses it seems like it. I was also a bit surprised about these stats from Astro’s homepage:
So, I tried rebuilding and converting my blog from Docusaurus to Astro gradually, without changing the design. I follow this basic tutorial about creating a blog with Astro
Astro Island Architecture hits different
I was surprised when I saw the results. Most Pagespeed Insights (Lighthouse) performance scores for my post pages are increased, mostly to 95%+ for desktop, and 85%+ for mobile. Homepage hit a 100% performance score for desktop, with 90%+ for mobile before I fine-tuned it.
The other lighthouse metrics (Accessibility, Best Practices, and SEO) were not optimized until recently. They are mostly just HTML code optimization, so its easier to improve them with any frameworks. What really matters is the Performance metric.
It’s like loading a website in localhost.
I never thought that I could achieve this with little effort. Back in the day when I used WordPress, I needed to use multiple plugins like image optimizer (lossless), html/css/js minifier, cache strategy, etc and still got lower performance scores.
I’m not saying that we can’t do this with WordPress. It just will take a lot more effort to achieve this with WordPress.
Now, the only thing I need is optimizing images by converting to .webp
using Webp Converter before i use them on my blog posts.
If you check the images in this blog, I don’t even resize them!. It’s still in original size, mostly 1600x800 resolution for cover image. Yet, I still got 100% performance on the home page and 95%+ performance score in almost every post.
It seems Pagespeed Insights ignores the diagnostic errors if the speed index is lower than 1s.
I inspected the HTML element for each page, and I found out that it was because Astro loads javascript effectively with its Island Architecture.
By default, every page in Astro has 0 javascript until we add it manually. It also didn’t mix the javascripts from other pages into one file, making it only load necessary javascript codes for every page.
Developer Friendly
Another thing that I like about Astro is it’s simple and easier to learn compared to other SSG libraries. I almost never get stuck or searching in Google when migrating to Astro. I mostly just read the official documentation.
Astro component is similar to JSX. For instance, this is the .astro
file for my blog home page.
---
import { SITE_TITLE, SITE_TAGLINE, SITE_DESCRIPTION } from '../consts';
import { getCollection } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro';
import PostList from '../components/PostList.astro';
import RecommendedPosts from '../components/widgets/RecommendedPosts.astro';
import ResourceMenuList from '../components/ResourceMenuList.tsx';
import { LucideChevronRight } from 'lucide-react';
const posts = (await getCollection('blog')).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()).slice(0, 10);
---
<BaseLayout title={SITE_TITLE + ' - ' + SITE_TAGLINE} description={SITE_DESCRIPTION} withBgImage>
<div class='container lg:grid lg:grid-cols-12 space-y-8 lg:space-y-0 lg:gap-8 px-3'>
<div class='w-full lg:col-span-12 sm:min-h-72 py-6 flex flex-col items-center gap-8'>
<div class='sm:max-w-[700px] px-3 mx-auto text-center leading-none'>
<h1 class='text-xl sm:text-[40px]/[1] font-[900] my-3'>{SITE_TAGLINE}</h1>
<p class='text-base sm:text-xl'>
{SITE_DESCRIPTION}
</p>
</div>
<ResourceMenuList />
</div>
<main class='lg:col-span-8'>
<PostList posts={posts} />
<nav class='flex justify-end gap-4 mt-8' aria-label='Blog list page navigation'>
<a
class='flex gap-2 items-center font-semibold text-inherit hover:text-[var(--color-primary)] bg-[var(--background-surface-color)] py-2 px-4 rounded-3xl border border-[var(--soft-border-color)]'
href='/page/2'>Older Entries<LucideChevronRight /></a
>
</nav>
</main>
<aside class='lg:col-span-4'><RecommendedPosts /></aside>
</div>
</BaseLayout>
Cut 100% of Hosting Costs
Deploying a static website (with any framework) doesn’t need paid hosting. There are a lot of reliable free hosting services you can use to host your static build files such as Vercel, Netlify, Github pages, and Cloudflare pages.
All of them offer a generous free tier and can be pointed to a custom domain. After tiring all of them, I chose Cloudflare pages because it has unlimited bandwidth and is free for commercial use. The deployment is also easy.
After I completed my new Astro blog, I pushed it to Github. From Cloudflare pages, I set a deployment pipeline from my blog repository in Github. So, every time a commit is pushed to main
branch, Cloudflare pages will pull the main
branch, build and deploy it.
The setup is fairly easy. Just a few clicks and set the build command for the Astro project.
I stopped my local hosting subscription and only paid for domain registration. If somehow these free hosting services stopped working, I can just switch to another one, or subscribe to a cheap hosting that is enough to just host the static build files.
Migrating static website hosting is easy. You don’t need to a backup database or WordPress assets, because the real hosting is your GitHub repository.
Conclusion
The journey from WordPress to Astro.js has been transformative for my blogging experience. Migrating from a traditional CMS to a static site generator has significantly boosted my blog’s performance, making it faster and more efficient.
However, blogging with Astro requires more technical skills. If you can’t code in HTML/CSS/Javascript, you probably have to stick with WordPress. But if you are impressed with Astro’s performance and insist on implementing it to your blog, you probably need to hire someone like me to do the job :grin:
If you find this article helpful, please give it a like, and share it to Twitter, Reddit, or daily.dev.
Thank you, Happy coding! :grin: