Before we take a look at the performance improvements I made in the third iteration of my blog, let's take a tour back in time to when I built my first and second blog sites on the Jamstack.
To get straight to the data — click here.
2020: Svelte + Sapper
I built my first simple blog site in 2020 using Svelte and Sapper. The blog posts were powered by markdown files stored in the repository, and it was a great starting point.
2021: Next.js + Contentful
Throughout the year I continued to write blog posts, iterate and add functionality to the site to help developers use Next.js and Contentful together. But given the amount of features I loaded into the site, this version of my blog began to feel a little over-engineered. It was becoming more difficult to make small updates to the site, and the way I managed the content in such atomic ways felt more suited to a larger product team comprising multiple developers and content editors.
View the site to refer to later.
2022: Eleventy + Contentful
Full disclaimer: all tools are valid tools!
Before we get into the performance improvements I made switching from Next.js to Eleventy, I want to make it absolutely clear that all tools are valid, and me moving from Next.js does not mean I think it's a terrible tool! I think it's a great tool — especially for larger development teams that don't have the time to build their own software design patterns and scaleable architecture from the ground up. It's always super quick to get a large-scale production-ready app launched using Next.js!
Choosing your tools
Choosing a static site generator or front end framework for your new project should depend on a number of factors, including:
- What the project is and how it might grow (and this could also change!)
- How large your development team is
- Whether you need to cater for an editorial content team
- Who your end-users are, what devices they use, and where they are in the world!
My answers to these questions pushed me in the direction of building with a more lightweight solution than Next.js. Plus, this was a great opportunity to learn how to use yet another static site generator.
Additionally, more and more developers I have connected with over the last few months are using Eleventy to build lean, performant sites. I felt like this would be a good opportunity to learn from others, and help others in the process as well.
Now, let's look at the data!
In this study, success was measured against the following four objectives:
- Reduce network requests
- Improve all Core Web Vitals
- Improve Lighthouse performance scores
Performance was compared between the Next.js site and Eleventy site using three free tools: Google Lighthouse, web.dev/measure and Web Page Test. Lighthouse tests were run in Brave Browser dev tools, Web Page Test runs were conducted via the web app using the London, UK - EC2 server, and web.dev tests were conducted in the browser. Given that I advocate for mobile-first development — and that's where performance is most likely to be impacted given the unpredictable speed of mobile data — all tests were conducted in an emulated mobile environment using a medium 3G network speed, on iPhone 6/7/8.
Using Web Page Test, I looked at the breakdown by MIME type of the home page for both sites.
In comparing the visual design of the Next.js site with the Eleventy site, you might argue that the two home pages are so vastly different that there are bound to be such discrepancies. But this is down to the differences in how Next.js and Eleventy build and bundle files for production.
What's also important to note is that design is performance. I made a bunch of design decisions during the migration with performance in mind and to cut down on third-party dependencies. This included:
- removing the "latest YouTube video" from the home page
- removing Google Analytics from the whole site
- self-hosting fonts rather than requesting them from the Google Fonts CDN
Reduce network requests
The Eleventy home page makes just 9 network requests, totalling just 325.5kb.
This makes the new home page just 8% of the size of the old home page! The largest payload on the Eleventy site comes from font files — which I could do well to optimise further in the future.
✅ Reduce network requests — success!
Improve Core Web Vitals
Core Web Vitals are currently scored on three aspects of user experience — loading, interactivity and visual stability. These tests were conducted on the home page of both sites using web.dev/measure.
Loading performance is measured by the Largest Contentful Paint (LCP). To provide a good user experience, the LCP should happen within 2.5 seconds of when the page first starts loading.
And the results:
- Next.js site — LCP = 9.9s
- Eleventy site — LCP = 1s
✅ Improve LCP — success!
Interactivity is measured by the First Input Delay (FID) and measures how soon your web application responds to user input such as clicking buttons, selecting text and typing into form fields. It's difficult to accurately measure FID as it involves testing with real users, so we can use the Time to Interactive (TTI) metric to calculate how long a page takes to become fully interactive.
And the results:
- Next.js site — TTI = 11s
- Eleventy site — TTI = 2.5s
✅ Improve TTI — success!
Visual stability is measured by Cumulative Layout Shift (CLS). Have you ever clicked on a part of a web page, only to find that you unexpectedly clicked on something else after a rogue element or image was finally loaded? CLS is where content pops into view once it has loaded, often pushing content down or sideways on the web page — and can be extremely frustrating! A good user experience maintains a CLS score of 0.1 or less.
And the results:
- Next.js site — TTI = 0.002
- Eleventy site — TTI = 0.032
😬 Improve CLS — not really! It's still way below 0.1, which is good! But I'm really not sure what increased the CLS on the Eleventy site! This needs more investigation.
Here are the test results from a single run of web.dev/measure for comparison. Green numbers all round!
Improve Lighthouse performance scores
Given that I had focussed on the home page only in previous tests, I also tested the Google Lighthouse performance score of various blog posts with different characteristics to ensure I'd made an improvement across the site.
Here's our baseline, showing a great improvement from 73 to 100!
A long blog post with lots of code examples
Lighthouse performances scores are often impacted by an "excessive DOM size", which for my blog posts, is usually the result of large code examples and the way the code snippets are highlighted using lots and lots of
<span> tags. This blog post saw a great improvement on performance from 89 to 100.
A long blog post with lots of images
I did a lot of work on the Next.js blog with regards to optimising image formats for different browsers, and lazy loading those images where supported. The score still improved from 98 to 99, though! Read the blog post linked below to learn more about how to load responsive images in AVIF and WebP using the HTML tag!
A blog post with a YouTube video embed
✅ Improve Lighthouse performance scores — success!
The second system effect
Reflecting on the journey my blog iterations have taken reminds me of the Second System Effect. The first implementation wasn't scaleable enough for me, the second implementation was slightly over-engineered, and the third iteration is just about right — for now — thanks to all I've learned along the way!
So, do I recommend you build your next blog site with Eleventy? It depends!
Use the right tool for the job
People often ask me what front end framework or static site generator they should get started with, and my answer is always — it depends! The most solid advice I can give you is to decide on the features you want, decide how you might need to scale the application (in terms of team size, content management, systems and patterns), and don't be afraid to try things out. You might not get it right first time, but always endeavour to use the right tool for the job. Try not to over-engineer, and always be mindful of what you're asking your site visitors to download to their browsers. You can check out a huge list of static site generators over on Jamstack.org.
Through iterating the technology stack used for my blog, I've learned how to use three front end frameworks, how to power a blog using markdown files or a CMS — and how all of these things contribute to the developer experience, and end-user experience of a website.
As always, I would encourage you to build stuff, learn things, and love what you do. Try things, ship things, and iterate, iterate, iterate.
Top comments (11)
Taking on the migration from Next.js to 11ty was likely - significant.
Astro could be seen as an alternative, capable of producing similar results without having to sacrifice the amenities of their chosen component framework.
You're not wrong! I've got a blog post in the works that will explain my process... kind of an "Eleventy for Next.js developers" approach.
Astro is next on my list to look at for a project I'm working on!
Yes! Astro has gained a lot of traction, and the things which you can do with it are absolutely nothing short of amazing. Considering most portfolios are static, astro is a perfect fit.
And for SSR, Nextjs has always been there but now there's Remix, giving developers more choice and freedom.
Didn't know this existed.
But looking at it, from a first glance, it seems to be very early in development therefore (probably) lacking libraries and support that Next has, such as [NextAuth(next-auth.js.org/). There also isn't much support for stuff like custom middleware. But sure, it'll fulfill the needs of your CRUD todo app.
I would implement the ways you mentioned in one of my prod application. Tbh I always looked for lighthouse and worked on improving the score. The tools you mentioned seems pretty cool and useful, thanks for writing
So happy to help, Aniket!
This is definitely interesting. I just checked out your website, and it looks 100% static, so I don't exactly see the need for you to use Nextjs if I'm being honest.
I believe you're absolutely right about "use the right tool for the job", because, quite frankly, Nextjs is not the right tool for a static portfolio website. Something like 11ty or my personal favourite, zola (static site generator in Rust). Most static site generators are really fast, the only one I really dislike is Gatsbyjs.
Love a good performant site. Frameworks like react are so good when you need them, but really add kb's with little benefit.
I would be interested to hear how 11ty compared to sapper?
You can run the measurement yourself against the current deployment; performance is 26.
Sapper has been replaced with SvelteKit - but as it is still based on a client-side rendered framework it still has to hydrate on the client-side - something a typical 11ty site doesn't have to do (unless something like Slinkity is used to support client side components).
I’ve come so far since I built that site. Don’t even look at how big that banner image is 😵💫 I could definitely optimise this site but… won’t fix 😂