Skip to main content

Nuxt Scripts: Load And Optimize Third Party Code

· 7 min read
Jakub Andrzejewski

Third-party scripts are often among the biggest performance bottlenecks on modern websites. From analytics and tracking to chat widgets and A/B testing, these scripts can block page content from rendering, increase CPU usage, and slow down user interactions.

In this article, we’ll focus specifically on how to optimize third-party scripts in Nuxt, covering both the Nuxt Scripts module and Nuxt Partytown. We’ll go beyond the basics, looking at advanced usage patterns and combining these tools for maximum performance benefits.

Introduction: third-party code on the web

Third-party scripts are everywhere on the modern web: websites load analytics, ads, chat widgets, or A/B testing tools from an external provider.

While they add essential functionality, they can also be one of the biggest drains on performance. Every new script risks blocking rendering, slowing down interaction, or eating up valuable CPU time.

You can see a real-world example of that in the request waterfall below.

Network request waterfall showing third-party requests

In this article, we’ll take a Nuxt-specific look at the problem of third-party scripts impacting page speed.

Challenges when loading third-party scripts in Nuxt

When working with third-party scripts, you always need to account for two states:

  1. Before the script has loaded
  2. After the script is ready and its API can be used

In SSR mode, the first server-rendered page load skips the “before load” state. But when navigating client-side to a page that injects a third-party script, you’ll need to handle that state explicitly. Sometimes even the mounted hook fires before the script finishes loading.

This can cause problems when your app depends on a script’s API, such as with Google Maps. Without proper handling you risk race conditions or missing references.

To solve this issue, we need to take control of how the scripts are loaded in the application.

Add scripts to the head with Nuxt useHead

The recommended approach to handling scripts in a default Nuxt project is using the underlying useHead composable coming from the Unhead package.

<script setup lang="ts">
useHead({
script: [
{
src: "https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY",
defer: true,
},
],
});
</script>

<template>
<div>
<!-- How can I be sure Google Maps API is ready here? -->
<GoogleMapsComponent />
</div>
</template>
tip

The defer attribute ensures the script doesn't block all rendering on the page.

You can learn more about it here. Apart from just adding the script, we could also utilize the tagPosition property that allows us to define where this script should be added (head, bodyOpen, or bodyClose).

How to handle scripts efficiently with Nuxt Scripts

In the Nuxt ecosystem, you can use the Nuxt Scripts module to gain fine-grained control over how scripts load (async, defer, lazy, etc).

First, add the module in nuxt.config.ts:

export default defineNuxtConfig({
modules: ["@nuxt/scripts"],
});

Nuxt Scripts provides both a general-purpose useScript composable as well as more specific helpers like useScriptTriggerConsent or useScriptGoogleMaps.

For example, in your component you can call the useScriptGoogleMaps composable and load the Google Maps JavaScript code just when it is needed to not block the load of the page.

<script setup lang="ts">
const { onLoaded } = useScriptGoogleMaps({
apiKey: "key",
});
const map = ref();
onMounted(() => {
onLoaded(async (instance) => {
const maps = await instance.maps;
new maps.Map(map.value, {
center: { lat: -34.397, lng: 150.644 },
zoom: 8,
});
});
});
</script>

<template>
<div ref="map" />
</template>

This way, you can define all third-party scripts declaratively. No messy <script> tags in your templates!

Alternatively, take full control over the script by using the useScript composable instead:

useScript(
{
src: "https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places",
defer: true,
crossorigin: "anonymous",
},
{
trigger: new Promise((resolve) => setTimeout(resolve, 3000)),
}
);

Check out all available options in the useScript documentation.

Using Partytown in Nuxt applications

Another great addition to more efficient handling of third-party scripts is PartyTown.

That allows moving heavy computations out of the main thread to the worker. In Nuxt, you can install the official @nuxtjs/partytown module.

Then, in nuxt.config.ts you can forward analytics calls to the web worker thread:

export default defineNuxtConfig({
modules: ["@nuxtjs/partytown"],
partytown: {
forward: ["dataLayer.push"], // forward analytics calls to the worker
},
});

Finally, place your third-party script in app.html and see the magic happen.

Using Nuxt Scripts Together with Nuxt Partytown

While Nuxt Scripts gives you control over when and how a script is loaded, Nuxt Partytown can take things a step further by moving third-party scripts into a web worker. This reduces main-thread work and helps keep your app responsive, especially if you rely on heavier libraries like Google Maps, analytics, or chat widgets.

To combine both tools, you load the script using useScript from Nuxt Scripts, but also mark it with type: 'text/partytown'. This tells Partytown to execute the script in a worker instead of blocking the main thread.

Here’s what it looks like for Google Maps:

<script setup lang="ts">
const map = ref();

const { onLoaded } = useScriptGoogleMaps(
{
key: "YOUR_API_KEY",
libraries: ["places"],
type: "text/partytown", // 👈 run in Partytown worker
},
{
trigger: true, // load immediately (could also be consent-based)
}
);

onLoaded(async (instance) => {
// Initialize the map once the API is ready
const maps = await instance.maps;
new maps.Map(map.value, {
center: { lat: 40.7128, lng: -74.006 },
zoom: 10,
});
});
</script>

<template>
<div>
<div ref="map" />
</div>
</template>

Using them together gives following benefits:

  • Nuxt Scripts: Gives you declarative control over loading, conditional triggers (e.g. GDPR consent), and warmup strategies (e.g. preconnect).
  • Nuxt Partytown: Offloads execution to a worker, keeping the main thread light and interactions smooth.

For libraries like Google Maps, which can be heavy but not always required immediately, combining the two tools lets you load them asynchronously, conditionally, and without blocking the UI.

Practical Workflow

Consider using Partytown to move third-party execution into a web worker. This keeps the main thread focused on rendering and interaction, while still allowing external scripts to run.

In Nuxt, pairing @nuxt/scripts with @nuxt/partytown lets you both control when scripts load and offload their execution, a useful combination for cases like analytics after cookie consent.

By layering these strategies—simple loading attributes, lazy loading, self-hosting, and finally workers—you can keep your site fast while still benefiting from third-party services.

Summary

Loading third-party scripts in Nuxt is now simpler than ever. With Nuxt Scripts and Nuxt Partytown, you can manage external dependencies in a clean, performant way.

Nuxt Scripts gives you fine-grained control over when and how scripts are loaded, while Partytown moves heavy third-party scripts into a web worker, keeping the main thread free and your app more responsive.

For Nuxt projects, this combination makes integrating third-party libraries more maintainable, improves runtime performance, and can even reduce input delay caused by blocking scripts.

tip

Trying to make your Nuxt app faster? Check out our guide to Nuxt performance and learn how to make your website faster.

Measure the impact of your web performance optimizations

You can use DebugBear to measure whether the changes you're making to your Nuxt app result in better user experience for your visitors. Measure page load time and Google's Interaction to Next Paint metric to see if your metrics are improving and identify what's causing slow performance.

Real user monitoring dashboard

By using the Long Animation Frames API, DebugBear can surface scripts that slow down interactions or the initial page load for real users.

That allows you to identify specific third-party scripts that are slowing down your website and focus your optimizations on them.

INP primary script breakdown

Illustration of website monitoringIllustration of website monitoring

Monitor Page Speed & Core Web Vitals

DebugBear monitoring includes:

  • In-depth Page Speed Reports
  • Automated Recommendations
  • Real User Analytics Data

Get a monthly email with page speed tips