DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,673 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Improve your website performance using Partytown type in script tags
Axel Navarro for Cloud(x);

Posted on

Improve your website performance using Partytown type in script tags

Can we use Google Tag Manager from a web worker? Is <script type="text/partytown"> a new standard? Let's see what this new script type is and how we can easily move workloads from the main thread to a worker with an example using GTM and Next.js. After that you can implement this with vanilla JS and other third party scripts like Facebook Pixel, Mixpanel, Amplitude, etc.

What is Partytown πŸŽ‰?

Partytown is a library that helps us to relocate scripts into a web worker creating communication channels, like dataLayer.push() which is used in GTM. If GTM was loaded into a worker, every call to dataLayer.push() should be forwarded from the main thread to the worker thread, and Partytown solves that automatically! Also, it allows code executed from the web worker to access DOM synchronously, so third-party scripts can run exactly how they were coded and without any alterations.

Without Partytown and With Partytown: Your code and third-party code compete for main thread resources

Creating script tags for workers

To run code in the worker just use type="text/partytown". The browser won’t recognize that type ignoring the script tag and then Partytown will load that script inside a web worker. This works for inline code or files.

<script type="text/partytown">
  /* GTM Script Here */
</script>
<script type="text/partytown" src="https://example.com/analytics.js"></script>
Enter fullscreen mode Exit fullscreen mode

Where is the forward?

To forward a function call to the worker we just need to add the configuration to the window object before the inlined Partytown script.

<script>
  window.partytown = { forward: ['dataLayer.push'] };
</script>
<script type="text/partytown">
  /* GTM script here */
</script>
Enter fullscreen mode Exit fullscreen mode

Now, you can use window.dataLayer.push() from the main thread. πŸ™Œ

Using workers in Next.js

Setting up Partytown in a Next.js website is very easy! We just need Next.js v12.1.1 or later.

🧠 Remember that this is an experimental feature in Next.js and it’s not covered by semver. πŸ™€

First, we should enable the experimental flag in the next.config.js file.

module.exports = {
  experimental: { nextScriptWorkers: true }
};
Enter fullscreen mode Exit fullscreen mode

And install the Partytown package.

npm install --save-dev @builder.io/partytown
Enter fullscreen mode Exit fullscreen mode

The Next.js workers don't require extra configurations, but we should forward the dataLayer.push for this example. We need to include this configuration in a <Head> component inside a custom _document.js.

import { Html, Head, Main, NextScript } from 'next/document'

const Document = () => (
  <Html>
    <Head>
      <script
        data-partytown-config
        dangerouslySetInnerHTML={{
          __html: `
            partytown = {
              lib: '/_next/static/~partytown/',
              debug: true,
              forward: ['dataLayer.push']
            };
          `
        }}
      />
    </Head>
    <body>
      <Main />
      <NextScript />
    </body>
  </Html>
);

export default Document;
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ The debug: true setting gives us nice info in the DevTools' console.

Finally, we can add the GTM script in our _app.js.

import Script from 'next/script'; 

const MyApp = ({ Component, pageProps }) => (
  <>
    <Script
      id="gtm-script"
      strategy="worker"
      dangerouslySetInnerHTML={{
        __html: `/* GTM script here */`
      }}
    />
    <Component {...pageProps} />
  </>
);

export default MyApp;
Enter fullscreen mode Exit fullscreen mode

The id property is required for inline scripts in order to let Next.js track and optimize the script.

And it's done! Your GTM runs in a worker that you can communicate with using the dataLayer.push - as always.

You can find installation instructions for React, Angular, Nuxt and more.

Conclusion

Too much JavaScript can block DOM construction, delaying how quickly pages can render. Reducing JavaScript in our main thread is a good strategy to reduce the time until interaction. This will free up main thread resources so they can be used for the primary web app execution, e.g. network requests.

With Partytown we can use read and write main thread DOM operations synchronously from within a web worker; I wonder if this can be used in a microfrontend application to increase the responsiveness of our website.

I hope you find this helpful If you came here looking for performance improvements for your website. Do you have production experience with workers? Have you used Partytown before? Tell me in the comments.

Top comments (2)

Collapse
 
imthedeveloper profile image
ImTheDeveloper

Thanks for the overview. I have a slow bigcommerce site that could do with this!

Collapse
 
zeta22 profile image
Zeta Zarza

Nice post, wacho

Visualizing Promises and Async/Await 🀯

async await

☝️ Check out this all-time classic DEV post