Building WPDecoupled: Improving Performance

Alex Moon on

The time has now come to fine-tune the site and improve its performance! I sometimes forget all the little things I skipped over in the beginning. Most of what I will share in this post was discovered on account of an SEO audit. The clear issue that was surfaced was performance. So, I dove in and did some little and big optimizations.


Google’s Lighthouse tool squawked at me about self-hosting my fonts. I recall knowing I should do this when I designed the site. Ultimately, I used Google Fonts to load them because I wanted to get things working first and optimize them later. Step 1 was to download my fonts of choice Bungee Shade and Lora.

Both fonts came as uncompressed TTF (True Type Font) files. TTF is a great format for local fonts on a computer. Not so great for web fonts. WOFF2 (Web Open Font Format 2) was designed as an open spec with compression at its core (WOFF2 users Brotli!). I found this tool made quick and easy work of converting the TTF font files to WOFF2 formats.

Before I got too far I recalled 1 piece of optimization I had already done, and that Google Fonts makes easy. Font Subsetting. This is when you eliminate certain characters from a font file. If your website is in English and your font ships with non-Latin characters, you are shipping extra bytes that are not needed. But in my case, I was only using c, e, d, l, o, p, u, and w from Bungee Shade. This is cause Bungee Shade is the font I use in the header and will only ever be used to spell WPDecoupled. Meaning I could use font subsetting to eliminate all characters except these 8.

I found a great article on how to subset a font and a great tool that would convert to woff2 and subset at the same time! Between subsetting and the use of WOFF2, I eliminated a ton of bytes from my initial page load on the site, see for yourself:

Bungee Shade411.2 kB110.6 kB5.4 kB (🙀)
Lora Regular133.9 kB47.5 kB
Lora Bold133.8 kB47.9 kB
Lora Regular Italics139.3 kB51.3 kB
Lora Bold Italics140.3 kB50.9 kB
Data savings from using WOFF2 and subsetting my font.

To finish out my font optimizations I made sure to preload my fonts. This tells the browser to download these as soon as possible. For those unaware, a @font-face directive in your CSS doesn’t load a font. It tells the browser how to load a font. To optimize font loading and prioritize more important things the browser waits till it sees this page needs that font before fetching your favorite font. I know the site needs Bungee Shade on every page, and probably others too. So I have opted to tell the browser to preload all my fonts.

My fonts are now all served from the same domain as the site and I am serving optimized versions for my specific content. Page load saw a nice little boost from this move! For more info on optimizing your font loading check out this great article that helped guide me through this process.

I use Sentry for error monitoring. It’s been an interesting experiment as I haven’t done so before on a site. I am honestly still debating its value. It mostly tells me of all the ways script kiddies are trying to look for vulnerabilities on the site thinking it is classic WordPress and triggering 404 errors. I have gotten little valuable data out of it so far, but not nothing.

All this to say, Sentry scripts consistently came up as being a little cumbersome on the old performance metrics. I decided to check their docs to see if anything had changed. It had. SvelteKit was relatively new to the world of stable meta-frameworks when I first launched this site and Sentry’s integration was limited to the fact that it ran on node. I was able to integrate it but it required some manual work. They had since released a dedicated package that optimized things for SvelteKit and made the integration much easier.

Nothing crazy to report here, I think I will get better error coverage out of the upgrade and I think it reduced my bundle size, though I honestly did not pay too close attention.


I have mentioned before that I use the Sitemap that Rank Math provides by proxying requests from the frontend SvelteKit site to the WordPress CMS. That’s done through some basic code. The code is not important, but what was important is that I have had trouble with Google’s Bots not being able to read those sitemaps. They’ve always worked in my browser but Google has been slow to index the site. They didn’t provide error codes but I suspected a timeout was occuring.

The way I first wrote the code to proxy the sitemap request was to await resp.body.text(). That is to say, when SvelteKit received a request for the sitemap it asked WordPress for the file using fetch, then loaded the entire file into memory before sending the text as a response with appropriate headers.

This was slow. I’m moderately familiar with streams and knew that would probably fix the issue, I just was not sure about how hard it would be to do this. As a quick reminder, streams are a way to process smaller chunks of data instead of an entire dataset. In this case, Instead of making everyone wait for SvelteKit to download the file before letting the requesting Bot download it again, streams let SvelteKit pass the chunks of data on just as soon as they arrive. The code? resp.body That’s right! I could not believe it was so easy. Fetch gives us a readable stream to start and I just never knew!

Loading of sitemaps improved greatly and Google Search Console now reports healthy sitemaps! Yay! Hopefully, indexing is soon to follow.


I did some other random optimizations like updating the home page by updating the text, adding a meta description, and an H1 tag. I also set up Bing Webmaster tools to ensure all this great content is discoverable wherever you search!


Thanks for coming on this journey so far. I’m happy with where the site is at it is maturing and I’ve got time and ideas so there may be some cool things coming soon.

As always, hit me up on the socials if there’s a topic you’d like to see covered.

Alex Moon

About Alex Moon

Avid Open Source maintainer, a longtime developer, and vagabond.