In modern web development, integrating third-party scripts is a common practice, especially when working with frameworks like Nuxt.js. Whether it's payment gateways, analytics tools, or external APIs, many third-party services require adding scripts to your project. But how do you efficiently load these external scripts in Nuxt? In this article, we'll explore the best practices for handling third-party scripts in Nuxt, including the powerful Nuxt Scripts module, and guide you through the process of integrating them smoothly into your application.
Almost every modern web application is using some kind of dependency, even besides the preferred JavaScript framework.
While most of the dependencies are available through NPM, many of them also provide a link to a CDN (Content Delivery Network) version so it can be included in any project without additional efforts or build steps.
But there is also a fair amount of popular third-party libraries that don't provide an NPM package and rely fully on being implemented via the script tag. Common examples are newsletter integrations, contact forms, and the Stripe SDK to process payments.
Having only a CDN link brings some benefits like allowing seamless updates from the authors without having the developers to update their software but it also has it's drawbacks, especially when working with modern JavaScript frameworks.
The integration, especially when only needed on a single page, becomes more complex. In addition, developers have to deal with asynchronously loading scripts.
Let's see how we can add such third-party dependencies in our Nuxt project!
With Nuxt.js, loading third party scripts has been a breeze when they are needed everywhere. The only thing one would have to do is adding the corresponding link in the head
object of the project's nuxt.config.js
and unhead from unjs will do the heavy lifting.
// nuxt.config.js
app: {
head: {
title: "My awesome project", // Other meta information,
script: [{ hid: "stripe", src: "https://js.stripe.com/v3/", defer: true }],
},
}
This will defer the script but it will load it on every page, which is not suitable if you need it only certain pages like a payment page.
But thanks to Nuxt and Unhead, you can also include the script inside page components which will load it only on the pages where you've added the script.
To accomplish that, the useHead composable in the page components which works similar to the object in the nuxt.config.js
is the key. Here's an example using the Vue Composition API and Script Setup:
useHead({
script: [{ src: "https://js.stripe.com/v3/", defer: true }],
});
This looks quite similar to what we've done before, but it's not the final solution.
As explained in the introduction, developers have to deal with two states regarding a third-party script that is loaded in such a way: before it is loaded and when it is available.
When using Nuxt in SSR mode, the initial request to the page (where SSR kicks in) won't have the first state. If you navigate to the page containing a third party script after the first request though, the developers have to handle the additional state because even the mounted
Vue lifecycle hook might be executed before the script loaded.
<template>
<div>
<!-- How do I know when Strip is ready? -->
<SomeComponentDependingOnStripe />
</div>
</template>
<script setup lang="ts">
// /pages/payment-page.vue
useHead({
title: "Payment Page - My awesome project",
script: [{ src: "https://js.stripe.com/v3/", defer: true }],
});
</script>
Previously, when handling async script loading in Vue.js, I might have recommended a library like VueScript2. However, this often resulted in increased complexity and bundle size. The good news is that Unhead now offers a simpler and more efficient solution for managing head tags and external scripts in Vue 3, allowing for a more lightweight and flexible approach to handling third-party dependencies.
With Unhead, we can easily manage external scripts and ensure that logic depending on these scripts is executed only after they have been fully loaded.
Let’s adapt the previous example and use Unhead with the Composition API to load a script, conditionally execute logic when it's loaded, and chain multiple scripts that depend on each other:
<template>
<div>
<SomeComponentDependingOnStripe v-if="isStripeLoaded" />
</div>
</template>
<script setup>
const isStripeLoaded = ref(false)
// Using Unhead to load the Stripe script and run a callback after it loads
useHead({
title: 'Payment Page - My awesome project',
script: [
{
hid: 'stripe',
src: 'https://js.stripe.com/v3/',
defer: true,
async: true,
onload: () => {
isStripeLoaded.value = true
}
}
]
})
</script>
In this example, the Stripe script is loaded asynchronously, and the isStripeLoaded
flag is set to true
once the script has been loaded. This enables us to conditionally render the component that depends on Stripe only when the script is fully available.
Unhead also provides flexibility in loading scripts conditionally, making it easy to manage scripts that are needed only in specific scenarios, such as when a payment modal is triggered.
Another powerful way to load third-party scripts in Nuxt is by leveraging Nuxt Scripts. Nuxt Scripts is a feature of Nuxt that allows you to easily manage and load external scripts in a more structured and declarative way. Unlike the traditional method of injecting scripts manually, Nuxt Scripts automatically handles the script loading and provides additional optimizations for performance.
Here’s how you can implement the Stripe script loading using Nuxt Scripts with the useScriptStripe composable, focusing on our original example from the article:
<template>
<div>
<SomeComponentDependingOnStripe v-if="isStripeLoaded" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
const isStripeLoaded = ref(false);
const paymentEl = ref(null);
const { onLoaded } = useScriptStripe();
onMounted(() => {
onLoaded(({ Stripe }) => {
// Initialize Stripe and payment element when script is loaded
const stripe = Stripe("YOUR_STRIPE_KEY");
const elements = stripe.elements();
const paymentElement = elements.create("payment");
paymentElement.mount(paymentEl.value);
// Set flag to true once Stripe is ready
isStripeLoaded.value = true;
});
});
</script>
In this example, the useScriptStripe
composable is used to load the Stripe
script and initialize the Stripe Elements when it's ready. The onLoaded
callback ensures that the logic for creating the payment element and setting the isStripeLoaded
flag is executed only after the Stripe
script has successfully loaded. This approach provides a cleaner and more optimized way to manage Stripe integration in a Nuxt.js app using Nuxt Scripts.
By utilizing Nuxt Scripts, you avoid adding extra dependencies and simplify the management of external scripts. This method is not only more maintainable but also improves performance by ensuring scripts are loaded asynchronously and only when necessary.
Loading third-party scripts in Nuxt.js has never been easier, and with the introduction of Nuxt Scripts alongside Unhead, managing external dependencies has become even more streamlined and efficient. Nuxt Scripts provides a built-in solution for handling script loading, while Unhead allows you to manage async scripts and ensure that dependent logic is executed only after the script is fully loaded, without adding unnecessary complexity.
For Nuxt projects, leveraging both Nuxt Scripts and Unhead helps simplify the integration of third-party libraries. If you're working with Vue 3, adopting these tools can improve performance and reduce bundle size compared to older solutions. Be sure to stay updated with the latest versions to take full advantage of the features and improvements they offer.
I hope this article has given you valuable insights into how to load third-party scripts in Nuxt.js with Nuxt Scripts and Unhead. If you found this helpful, don't forget to share it with your colleagues or fellow developers who might benefit from this guide!
Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.
More than 200.000 users have already joined us. You are welcome too!
© All rights reserved. Made with ❤️ by BitterBrains, Inc.