Loading...
Loading...

Gatsby Partytown

Partytown is a lazy-loaded library to help relocate resource intensive scripts into a web worker.
Loading...
Loading...
2022-08-06
4 min read
Partytown WebWorker
Gatbsy Partytown WebWorker!

Partytown

🔗 Partytown By builder.io is a lazy-loaded library to help relocate resource intensive scripts into a web worker, and off of the main thread.

Its goal is to help speed up sites by dedicating the main thread to your code, and offloading third-party scripts to a web worker.

🔗 Gatsby Post On Partytown

🔗 Repo for the changes

Why is it important

It’s important because third-party scripts have a habit of slowing down the time it takes for your website to load, and a slow-to-load website isn’t good for users, or performance metrics…. or $business!

What we know: adding third-party scripts on the main thread impacts performance by delaying the time it takes for your site to become available and ready to use by your end users.

Offloading third-party scripts to a web worker

You can see from the below that amongst that mess on the Performance tab is the gtag script which is getting in the way of the application JavaScript – Blurg 🤢

Parytown Gtag scaled
Parytown Gtag scaled

You’ll also notice on the Network tab that js?id=G-ABC123 is actually loaded before some of the more essential application JavaScript – Yikes! 😲

Partytown Network Scaled
Partytown Network Scaled

But with Partytown, third-party scripts are offloaded to a web worker (which runs in its own thread), which means your site is available more quickly to your end users.

Your users thank you, your business thanks you, and we thank you for making a faster web!

Warning

⚠️ A word of warning

I should point out that Partytown is currently in BETA and the method I’m about to describe can also be considered BETA! – It does work but it could change in the future!

…but fear ye not! I have it on good authority that a Script component will be coming to Gatsby later in 2022 and all of the Partytown goodness I’m about to explain will be baked in and ready for you to use in the usual sweet, sweet Gatsby way! 💜

Oh also, before I forget, we’ve added some of the methods used in this post to the official Partytown docs, these can be found on the following links.

Partytown Builder.io

🔗 Integrations

🔗 Proxying Requests

My Implementation

I just changed my file’s like the plugin, gatsby-gtag-partytown, would do.

Remove any modules as in, gatsby-plugin-google-gtag or google analytics

uninstall
bash

gatsby-config.ts

gatsby-config.ts
ts

Add to .gitignore

.gitignore
diff

package.json

package.json
diff

gatsby-ssr.tsx

Google Analytics GA4 property

gatsby-ssr.tsx
tsx

There’s quite a lot going on here, so let me talk you through it.

onRenderBody

onRenderBody is one of gatsby-ssr’s extension points and runs after each page is created by Gatsby. It can be used to set HTML or elements.

gatsby-browser.tsx

gatsby-browser.tsx
tsx

To set <script /> tags in the HTML <head /> you can use the setHeadComponents function.

There’s an if condition right at the beginning to ensure the script tags and Partytown component aren’t added while in development

<script />

I’d like to draw your attention to the type on the tag. Usually you’d expect to see type=“text/javascript” but with Partytown this has changed to type=“text/partytown”. This is so later on, when Partytown does its thing it’s able to locate the tags to offload to web workers. More on that in a moment.

It’s also worth pointing out that the actual gtag script is ever so slightly different to the example given on the Google docs: Install the global site tag, i’ll explain why in a moment. – Read on 💅

<Partytown />

The <Partytown /> React component can be configured using regular React Jsx props. You can read more about the Partytown React component in the docs, but I will explain the forward prop as this is where things can get a little complicated.

The forward Prop “Problem”

If you have a look at Google’s recommended approach you might notice some differences between the code snippet i’ve used above and the one shown in: Add gtag.js to your site.

There’s a small but important difference shown here in the diff.

gtag
diff

When Partytown moves scripts into a web worker it creates a kind of clone of the window object, and when it does, function gtag() isn’t hoisted onto the cloned window object.

By defining window.gtag = function gtag() we can ensure that the gtag function as referenced by the forward prop will exist on the Partytown cloned window object.

Hat tip to Ward Peeters (Gatsby’s Principal Engineer, Tech Lead Open-Source) for this solution 🎩.

There’s one other small difference in the code snippet. Here’s the diff.

send_page_view
diff

To ensure that a page view isn’t sent once the script is loaded you can set send_page_view to false.

In the next section I’ll explain how you can fire off events containing location data. For reference here’s the Google docs for: Measure Google Analytics Events.

Sending events gatsby-browser.tsx

gatsby-browser.tsx
tsx

onRouteUpdate

The onRouteUpdate function is called when the user changes routes, including on the initial load of the page. You can access the current location from the destructured props.

As with onRenderBody there’s an if condition right at the beginning to ensure the gtag event isn’t called while in development, and then inside a 100ms setTimeout is where you can fire off any event you like. I’ve called this one page_view and passed in a pagePath which can be constructed from properties contained within the location prop. The 100ms delay is required to ensure all side-effects such as React Helmet setting titles etc are complete before the gtag event is fired.

Once deployed you can see on the Performance tab in Chrome Dev Tools that Partytown is now taking charge of loading the Google Analytics script and waits until the main thread has finished loading / parsing all of your important application JavaScript (indicated by the red line in the image below) – Lovely stuff! 🥳

Performance Scaled
Performance Scaled

gatsby-node.ts

gatsby-node.ts
ts

onPreBuild

The onPreBuild extension point is used to copy the ~partytown files into Gatsby’s static directory, this happens quite early on in the build process.

Once Gatsby’s build steps are finished Gatsby copies the files from the static directory into the public directory, ready for when Partytown needs them and when your site is served from your CDN.

It’s worth noting onPreBuild is only called during the build process.

If you need to use copyLibFiles while in development you can use onPreBootstrap which is called when running both gatsby build or gatsby develop.

Partytime!

And that’s it, it’s a little more work than slamming a tag in your HTML but offloading third-party scripts into web workers using Partytown will no doubt yield a substantial performance boost. In this demo, understandably, there’s not a huge perf boost but if you were to offload all of your third-party scripts you’d start to really get a taste of the vibe 😛.

What’s next?

This is a bit manual for now, but manual optimizations and those small efforts that can land in a big way. So rest assured, we’ll plan to make this even more seamless in the future!

Give 🔗 @GatsbyJs, 🔗 @GatsbyChangelog or Paul Scanlon, 🔗 @PaulieScanlon A follow on Twitter, and keep an eye out for updates.

You choose Gatsby because of your need for speed, and we want to make the fast thing, the easiest thing.

Loading...
Loading...
Loading...
Loading...
Loading...