It was overdue! With Nuxt 4 peeking around the corner, my personal website had been using Nuxt 2 and Node 14 for far too long. I didn't even have Nuxt Bridge layer. Publishing experience was super painful as I constantly had to update my dev environment before even running the site locally. The upgrade felt like a big chunk of work - thanks to huge number of modules and plugins I had accumulated over time in this project. Below, I’ll take you through how my old website was built before I undertook the revamp over the past few weeks.
While I have kept the diagrams landing page same as before, I have separated blog posts written on this website from the blog posts published else where on Publications page. I have stripped down all the transitions and images from the blog landing page. Now, blog landing page feels as quiet as a PDF! It’s super minimalistic and refreshing.
Diagrams landing page previously used three packages for it to function the way it did, such as, vue-infinite-loading
and vue-masonry-css
plugins for loading images on scroll in masonry grid, while it used vue-lazyload
for lazy loading images to improve page performance. This time around, I went ahead and wrote my own implementation of infinite loading images on scroll and masonry calculations of image grid that changes when viewport re-sizes - making both vue-infinite-loading
and vue-masonry-css
redundant.
Since the diagrams landing page is image-heavy, it pays a high performance price. Previously, I was using vue-lazyload
for lazy loading images. However, in my new blog, I have introduced @nuxt/image
module for all the images on my blog - even for those not on the diagrams landing page.
@nuxt/image
provides plenty of CDN providers out of the box, however, all of my images are served from AWS S3 bucket. So I wrote my custom provider.
<NuxtImg :src="post.image.src"
loading="lazy"
provider="s3"
:alt="post.image.alt"
/>
Previously, I used @nuxtjs/sitemap
to add sitemap that is powered by contents stored using Nuxt Content module. In the new version of the site, Nuxt content module provided this sitemap example where we can code up our own sitemap using sitemap
package. This method uses Nitro server route coupled with serverQueryContent
that provides us access to all the documents within /content
directory that we can loop through and write
required data to the sitemap.
// server/routes/sitemap.xml.ts
import { serverQueryContent } from '#content/server'
import { SitemapStream, streamToPromise } from 'sitemap'
export default defineEventHandler(async (event) => {
// Fetch all documents
const docs = await serverQueryContent(event).find()
// ...
for (const doc of docs) {
sitemap.write({
url: doc._path,
changefreq: 'monthly'
})
}
sitemap.end()
return streamToPromise(sitemap)
})
This gave me an idea to write my own RSS feed page as well since it shares pretty much the same contents. For this purpose, I used feed
package, and created new Nitro server routes that would create feed.xml
for my site.
// server/routes/feed.xml.ts
import { Feed } from "feed";
// ...
const feed = new Feed({ /* ... */})
for (const doc of docs) {
if (doc.Sitemap === true) {
feed.addItem({
title: doc.Name,
id: `https://krutiepatel.com/${doc._path}`,
link: `https://krutiepatel.com/${doc._path}`,
description: doc.description
// ...
});
}
}
// ...
Home page remains the same as before with major upgrade to the single card that sits in the center of the page with all the links of the website. Home page card design is inspired from my little cards UI project going on the Codepen. Footer still serves as a way to navigate the rest of the site when user is not on the home page.
Here's the final roundup of all the packages I used in my old website compared to the new one - trimming it down from 18 to just 7! I have reduced quite bit of packages this time, while introduced some new, essential ones for the first time. This streamlined approach not only makes my site cleaner and more efficient but also more tailored to my specific needs.
# | Old Website | New Website |
---|---|---|
# | Old Website | New Website |
1 | @nuxt/content | @nuxt/content |
2 | nuxt-windicss | @nuxtjs/tailwindcss |
3 | @nuxtjs/google-gtag | nuxt-gtag |
4 | aos | aos |
5 | @nuxtjs/markdownit | Vue Components support in Content module |
6 | vue-lazyload | @nuxt/image Lazy Load |
7 | @nuxtjs/feed | Custom wrote it using Nitro server routes and feed |
8 | @nuxtjs/sitemap | Custom wrote it using Nitro server routes and sitemap |
9 | dayjs | Replaced with native Intl |
10 | prism-themes | Content module highlight |
11 | vue-infinite-loading | Custom wrote it from scratch |
12 | vue-masonry-css | Custom wrote it from scratch |
13 | @iconify/vue | Replaced with custom tiny Vue Components |
14 | @nuxtjs/color-mode | Relies on the operating system preference |
15 | gsap | - |
16 | medium-zoom | - |
17 | vue-social-sharing | - |
18 | vue-tweet-embed | - |
This approach makes it much easier for me to upgrade my blog in the future without relying on external dependencies that much. By minimizing these dependencies, I aim to have more control over my site, making future upgrades much smoother and more manageable.
I hope you've enjoyed reading about my upgrade journey. Taking a little break from my book writing project to upgrade my website was a refreshing change. It gave me a fresh perspective and new insights that I can now bring back to my writing.