Improve your website performance using Partytown type in script tags
Tags: javascript, webdev, performance, react
Published: 2022-10-03 12:33:27

---
title: Improve your website performance using Partytown type in script tags
published: true
description: Move third-party scripts without any alterations to web workers using Partytown in React with Next.js.
tags: 'javascript, webdev, performance, react'
cover_image: 'https://raw.githubusercontent.com/cloudx-labs/posts/main/posts/navarroaxel/assets/using-partytown-in-next-cover.jpg'
id: 1189226
---

Can we use Google Tag Manager from a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)? 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](https://developer.mozilla.org/en-US/docs/Glossary/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](https://partytown.builder.io) 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](https://user-images.githubusercontent.com/452425/152393346-6f721a4f-3f66-410a-8878-a2b49e24307f.png)

### 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.

```html
<script type="text/partytown">
  /* GTM Script Here */
</script>
<script type="text/partytown" src="https://example.com/analytics.js"></script>
```

### 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`.

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

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](https://github.com/vercel/next.js/releases/tag/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.

```javascript
module.exports = {
  experimental: { nextScriptWorkers: true }
};
```

And install the Partytown package.

```bash
npm install --save-dev @builder.io/partytown
```

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`.

```javascript
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;
```

💡 The `debug: true` setting gives us nice info in the DevTools' console.

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

```javascript
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;
```

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](https://partytown.builder.io/react), [Angular](https://partytown.builder.io/angular), [Nuxt](https://partytown.builder.io/nuxt) and [more](https://partytown.builder.io/integrations).

## 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.