Partytown

repository·main·Indexed 9 days ago

https://github.com/qwikdev/partytown

A lazy-loaded library designed to relocate resource-intensive third-party scripts from the main thread into a web worker to improve site performance. Version 0.14.0 supports integrations with Angular and Astro, and utilizes Atomics and SharedArrayBuffer for optimized thread communication when browser and server configurations allow.

Tokens
28.1K
Snippets
109
Records
155
Agent score
94%

What's inside Partytown

  1. What is Partytown and how does it work?

    main

    Partytown is a lazy-loaded library designed to relocate resource-intensive third-party scripts (such as analytics, ads, and trackers) from the browser's main thread into a web worker.

    By offloading these scripts, Partytown frees up the main thread to focus exclusively on your primary web application execution, improving responsiveness and performance. It achieves this by:

    • Sandboxing: Controlling access to main thread APIs.
    • Isolating Tasks: Running long-running third-party tasks in a separate thread.
    • Batching DOM Operations: Reducing layout thrashing by grouping DOM setters and getters.
    • Synchronous Simulation: Reading and writing main thread DOM operations synchronously from within the web worker so that scripts execute as they were originally coded without alterations.
  2. Understand the Partytown package distribution

    main

    Partytown is distributed via NPM as @qwik.dev/partytown. The package is organized into several submodules, each serving a specific purpose in the ecosystem:

    • @qwik.dev/partytown/lib: Static files required for production (must be hosted on the same origin as your website).
    • @qwik.dev/partytown/integration: Low-level functions for building custom integrations.
    • @qwik.dev/partytown/react: React-specific components for easy setup.
    • @qwik.dev/partytown/services: Pre-configured event forwarding for common services like Google Tag Manager or Facebook Pixel.
    • @qwik.dev/partytown/utils: Developer utilities for managing library files and build tool integration.
  3. Understand the Qwik project structure

    main

    This project uses Qwik with QwikRouter for directory-based routing. The core directory structure is:

    • src/routes: Contains the routing logic. Use layout.tsx for hierarchical layouts and index.tsx for page content. index.ts files serve as endpoints.
    • src/components: The recommended location for reusable components.
    • public: Stores static assets like images. Files here are served directly by Vite.

    For more details on routing, refer to the Qwik routing documentation.

  4. How Atomics and SharedArrayBuffer work in Partytown

    main

    Partytown can use Atomics and SharedArrayBuffer to optimize communication between threads. When enabled, this provides several performance benefits over the standard service-worker communication layer:

    • Speed: Up to 10x faster communication between threads.
    • Size: ~5% smaller build files.
    • Network Efficiency: No proxytown requests in the network tab and fewer HTTP requests required to initialize the library.
    • Architecture: The Partytown service-worker and iframe are no longer used.

    Note: Atomics only work if the browser supports them and the server is configured with specific HTTP response headers. If these requirements are not met, Partytown automatically falls back to the service-worker communication layer.

  5. Handle throttled DOM operations in Partytown

    main
    DOM operations performed within the web worker are intentionally throttled. Because data must be sent and received between the worker and the main thread, blocking operations may take a few milliseconds longer than they would on the main thread. To mitigate this, Partytown batches most operations together to reduce the frequency of cross-thread calls.
  6. Configure Cloudflare Pages Function Invocation Routes

    main

    Cloudflare Pages uses a _routes.json file to determine which paths trigger a Worker Function (for SSR) and which paths are served as static files (SSG).

    Auto-generation

    By default, the Cloudflare adapter auto-generates dist/_routes.json during the build process. An example configuration might look like this:

    {
      "include": [
        "/*"
      ],
      "exclude": [
        "/_headers",
        "/_redirects",
        "/build/*",
        "/favicon.ico",
        "/manifest.json",
        "/service-worker.js",
        "/about"
      ],
      "version": 1
    }

    In this example, all paths are SSR'd except for the excluded static assets and specific paths like /about.

    Custom Configuration

    If you require more granular control, you can provide your own public/_routes.json file. If this file exists in the public directory, the Cloudflare adapter will use your committed version instead of auto-generating one.

  7. Understand the Service Worker communication fallback

    main

    When Atomics are not used, Partytown uses a Service Worker to facilitate synchronous-like communication. The workflow is:

    1. Scripts are marked with type="text/partytown" to disable main-thread execution.
    2. The Service Worker sets up an onfetch handler to intercept requests.
    3. The Web Worker executes the scripts and uses JavaScript Proxies to forward DOM calls.
    4. Proxy calls use synchronous XHR requests.
    5. The Service Worker intercepts these XHR requests and communicates asynchronously with the main thread.
    6. Once the main thread responds, the Service Worker returns the result to the Web Worker, making the call appear synchronous to the worker code.
  8. How Partytown handles browser feature support and fallbacks

    main

    Partytown is designed to be backward compatible. It uses Service Workers or Atomics to facilitate synchronous communication between the web worker and the main thread. If a browser lacks support for both, Partytown automatically falls back to executing scripts in the traditional way (on the main thread) to ensure functionality in legacy environments like IE11.

    Fallback Logic Hierarchy

    1. Atomics: Partytown first checks for Atomics support via the window.crossOriginIsolated boolean.
    2. Service Workers: If Atomics are unavailable, it checks for Service Worker support (the most common method).
    3. Traditional Execution: If neither Atomics nor Service Workers are supported, Partytown identifies all scripts with type="text/partytown" and resets them to behave as standard scripts, executing them normally on the main thread.
  9. Identify negative impacts of third-party scripts

    main

    Before implementing Partytown, it is helpful to understand the performance bottlenecks typically caused by unmanaged third-party scripts:

    • Main Thread Blocking: Excessive JavaScript parsing and execution can delay DOM construction and user interaction.
    • Network Congestion: High volumes of network requests to multiple servers.
    • CPU Strain: Intensive script execution can lead to battery drain and sluggishness.
    • Legacy API Issues: Use of harmful APIs like document.write().
    • Resource Bloat: Excessive DOM elements, expensive CSS selectors, or multiple framework embeds.
  10. Understand the Atomics communication layer

    main

    Atomics is the preferred communication layer for Partytown because it is approximately 10x faster than the Service Worker fallback for transferring data between the web worker and the main thread.

    When Atomics are enabled:

    1. The main thread loads the Atomics build instead of the Service Worker build.
    2. The Web Worker uses JavaScript Proxies to forward calls.
    3. Proxy calls use Atomics.store() and postMessage() to send data to the main thread, followed by Atomics.wait() to block.
    4. The worker uses Atomics.load() to retrieve the results once the main thread has processed them.