Nuxt Scripts

repository·main·Indexed 20 days ago

https://github.com/nuxt/scripts

A Nuxt module for loading third-party scripts with optimized performance, privacy, and developer experience. It features 20+ pre-configured integrations, built-in consent management, advanced loading triggers (such as onNuxtReady or element visibility), and the ability to serve scripts from your own origin via a privacy-focused proxy. Includes tools like useScriptNpm() for on-demand npm package loading and DevTools support for monitoring script status.

Tokens
121.1K
Snippets
408
Records
479
Agent score
69%

What's inside Nuxt Scripts

  1. Key features of Nuxt Scripts

    main

    Nuxt Scripts is designed to improve privacy, performance, and developer experience when handling third-party scripts in Nuxt applications.

    Core Capabilities

    • Performance Optimizations: Includes self-hosting capabilities, advanced script loading triggers, and best-practice defaults.
    • Privacy & Consent: Protects user identity by default and provides built-in APIs for script consent management.
    • Integrations: Offers 20+ pre-configured third-party script integrations.
    • Developer Experience: Includes DevTools support to view script status and function logs.
    • Lightweight: 0 dependencies with a ~2kb minimal runtime.

    Technical Foundation

  2. Manage overlay visibility with controlled or uncontrolled states

    main

    You can manage the visibility of an overlay using two patterns:

    1. Uncontrolled (Component-managed): The overlay manages its own state. It is open by default. Use :default-open="false" to start the overlay in a closed state. Note that uncontrolled overlays starting closed cannot be opened programmatically later.

    2. Controlled (Parent-managed): Bind v-model:open to a parent ref. This is the recommended pattern for popups or any overlay that needs to be toggled by user interaction (like clicking a marker). When v-model:open is bound, the defaultOpen prop is ignored; use the initial value of your bound ref instead.

    Tip: Using v-model:open keeps the component mounted and toggles visibility via CSS, which is more performant than using v-if as it avoids remounting costs and preserves internal state.

    <script setup lang="ts">
    const open = ref(false)
    </script>
    
    <template>
      <ScriptGoogleMaps api-key="your-api-key">
        <ScriptGoogleMapsMarker
          :position="{ lat: -34.397, lng: 150.644 }"
          @click="open = !open"
        >
          <ScriptGoogleMapsOverlayView
            v-model:open="open"
            anchor="bottom-center"
            :offset="{ x: 0, y: -50 }"
          >
            <div class="custom-popup">
              <button @click.stop="open = false">×</button>
              <p>Any Vue content here</p>
            </div>
          </ScriptGoogleMapsOverlayView>
        </ScriptGoogleMapsMarker>
      </ScriptGoogleMaps>
    </template>
  3. Understand `<ScriptInstagramEmbed>` limitations and behavior

    main

    How it works

    1. Server-side fetch: Nuxt fetches the Instagram embed HTML from {postUrl}/embed/.
    2. Asset proxying: Images from Instagram's media hosts and assets from static.cdninstagram.com are rewritten to proxy through your server.
    3. Script removal: Nuxt removes Instagram's embed.js to allow for static rendering.
    4. Caching: Responses are cached at the server level for 10 minutes.

    Browser Privacy

    The rendered embed loads no Instagram JavaScript, forwards no Meta Set-Cookie response, and sends image/asset requests to your Nuxt server. Instagram sees the server's connection rather than the visitor's.

    Limitations

    • Single-image only: Only supports single-image posts; galleries will only show the first image.
    • Static Videos: Videos are displayed as static poster images.
    • Reduced Interactivity: Interactive features like likes and comments are not available.
    • Endpoint behavior: The image endpoint rejects redirects, while the static-asset endpoint follows them without revalidating the destination host.
  4. What are facade components and why use them?

    main

    Facade components are lightweight placeholder UI elements that wrap third-party scripts (like video embeds, payment modals, or chat widgets).

    They solve two main problems:

    1. Performance: They defer the heavy resource fetching required by third-party vendors until necessary.
    2. Layout Stability: They reserve the necessary space in the DOM to prevent Cumulative Layout Shift (CLS) when the real UI is eventually inserted.

    Trade-offs to consider:

    • Visual Mismatch: The placeholder might not perfectly match the final UI.
    • Interactivity Delay: Users cannot interact with the real element until the script loads.
    • Accessibility: You must ensure loading and error states are announced clearly to assistive technologies.
  5. Understand the MapLibre stack components

    main

    When using ScriptMapLibreMap, it is important to distinguish between the rendering engine and the data sources. MapLibre GL JS only handles the rendering and interaction; it does not provide the map data itself.

    • MapLibre GL JS: The engine that renders vector or raster sources using WebGL.
    • Style JSON: A configuration file that defines sources, layers, fonts, icons, colors, and labels.
    • Tile service: The host for the vector or raster tiles referenced by the Style JSON.
    • Geographic data: The underlying data (roads, places, etc.) that populates the tiles.
  6. Loading third-party scripts with Nuxt Scripts

    main

    Nuxt Scripts allows you to control exactly when third-party scripts are executed to optimize performance and user experience.

    Key loading features include:

    • Default Trigger: Scripts load using the onNuxtReady trigger, which executes after hydration during an idle period.
    • Custom Triggers: You can trigger scripts based on user consent, element visibility, user interaction, or specific application states.
    • First-Party Mode: Supported scripts can be served directly from your own origin to reduce third-party overhead.
  7. How First-Party Mode works

    main

    First-Party Mode routes third-party script traffic through a reverse proxy on your own domain to improve privacy and bypass some ad blockers. It consists of three main mechanisms:

    1. Bundling: During nuxt build, third-party scripts are downloaded and served as local assets from /_scripts/assets/[hash].js. This avoids direct DNS/connection setup to the vendor.
    2. Reverse Proxy: Runtime requests (beacons, pixels, etc.) are intercepted and forwarded through Nitro server routes at /_scripts/p/. This is achieved via build-time AST rewriting and client-side runtime wrappers that redirect fetch, sendBeacon, XMLHttpRequest, and Image calls.
    3. Anonymization: The proxy can anonymize IP addresses (to subnet level) and strip sensitive headers like cookie and authorization before forwarding requests.

    Note: Anonymization reduces network and fingerprinting data but does not make an identified analytics payload (containing uid, email, etc.) anonymous if the SDK itself sends that data.

  8. SPA navigation in Ahrefs Web Analytics

    main
    Ahrefs Web Analytics supports Single Page Application (SPA) navigation natively. The underlying analytics.js patches history.pushState and listens for popstate events. This means that in a Nuxt application, route changes will automatically trigger fresh page views without requiring any additional manual configuration.
  9. How `<ScriptGoogleMapsStaticMap>` handles sizing

    main

    The component manages the size parameter for the Google Static Maps API request based on the environment:

    1. Client-side: It measures the rendered container's pixel dimensions on mount and clamps the value to the Static Maps API limit of 640x640 (preserving aspect ratio).
    2. SSR (Server-Side Rendering): It derives the size from the width and height props if both are provided as pixel values.
    3. Fallback: If no size can be determined, it defaults to 640x400.

    To bypass this automatic measurement and ensure consistent API requests, provide the size prop explicitly (e.g., :size="'800x600'").

  10. Use Partytown with `useScript()`

    main

    Setting partytown: true in useScript() options allows you to run a supported registry script in a web worker using Partytown. This requires @nuxtjs/partytown to be installed and configured.

    Important Limitations: When partytown: true is enabled, it takes an early SSR path. It immediately writes a <script type="text/partytown" src="…"> tag. This mode:

    • Ignores trigger, use, beforeInit, and warmupStrategy.
    • Ignores other script attributes and options.
    • The returned stub reports loaded immediately.
    • load() is a no-op.
    • remove() only disconnects DevTools observation.
    • proxy, reload(), and lifecycle callbacks are not available.

    Treat the Partytown return value as an implementation detail.

    // Requires @nuxtjs/partytown
    useScript('https://example.com/registry.js', {
      partytown: true
    })