Master third-party script optimization using Partytown and Web Workers. Learn how to stop main thread blocking and keep your site fast and responsive.
Last month, I spent about three days debugging a sudden spike in Interaction to Next Paint (INP) scores on an e-commerce dashboard. The culprit wasn't our own code; it was a bloated marketing tag manager firing five different tracking pixels, a chatbot widget, and a heat-mapping tool all at once. Every time a user clicked a button, the browser was busy executing third-party JavaScript, leading to a noticeable, sluggish delay.
If you’ve ever stared at a waterfall chart in Chrome DevTools and seen a sea of red bars caused by external scripts, you know the pain. We're often forced to include these tools by stakeholders, but they shouldn't cost us our user experience.
The browser’s main thread is the heart of your application. It handles parsing HTML, calculating styles, executing your application logic, and responding to user input. When you drop in a standard <script> tag for a third-party service, you are essentially giving that script permission to steal time from your main thread.
If that script is heavy or synchronous, the browser stops everything else to process it. This is exactly why we often struggle to keep our Core Web Vitals in the green. While you might have already implemented Critical CSS: How to Stop Render-Blocking CSS and Boost Speed or optimized your fonts as discussed in Font Loading Strategy: Eliminate FOIT and Layout Shifts, third-party scripts remain a persistent bottleneck.
Partytown is a library that allows you to move resource-intensive third-party scripts into a Web Worker. By running these scripts in a separate thread, they no longer block the main thread from handling user interactions.
Think of it this way:
Getting it running is fairly straightforward, though it requires some configuration. First, install the package:
Bashnpm install @builder.io/partytown
Next, you need to copy the library files to your public directory so they are accessible to the browser. If you're using a framework like Next.js or Vite, you can usually automate this through a plugin or a build step that copies @builder.io/partytown/lib into your /public/~partytown folder.
To actually use it, you change your script tags. Instead of a standard src, you use type="text/partytown":
HTMLstyle="color:#808080"><style="color:#4EC9B0">script type="text/partytown" src="https://example.com/analytics.js">style="color:#808080"></style="color:#4EC9B0">script>
When the browser sees that type, it ignores the script during the initial parse and lets Partytown handle it inside a Web Worker.
I’ll be honest: Partytown isn't a magic wand. It works by creating a "proxy" for the DOM. Because Web Workers don't have direct access to the DOM, Partytown creates a synchronized interface that allows the worker to read and write to the DOM indirectly.
We first tried moving our entire analytics suite over, but we ran into issues with a legacy tracking script that relied heavily on synchronous document.write calls. It broke immediately. We had to keep that specific script on the main thread and only move the modern, async-friendly scripts.
Also, be mindful of:
I usually reserve this for when I see a clear correlation between third-party script execution and long tasks in the Chrome Performance tab. If your INP is high and your "Total Blocking Time" (TBT) is dominated by external scripts, Partytown is a fantastic tool to have in your arsenal.
If you're already offloading heavy processing tasks, you might also be familiar with Web Workers and OffscreenCanvas for Jank-Free UI Performance. Moving scripts is just another extension of that same "don't block the main thread" philosophy.
I’m still experimenting with how much logic I can safely push into workers without hitting serialization limits. It’s a delicate balance. The goal isn't to be a purist about having zero scripts on the main thread; the goal is to make sure your users don't feel like the site is broken when they click a button.
Start small. Offload one non-critical tracking pixel and measure the impact on your TBT. You might be surprised at how much breathing room you can give your main thread with just a few lines of code.
Service Workers and stale-while-revalidate strategies help you achieve offline-first performance. Learn how to master the Cache API for instant loading.