惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

The Nuxt Blog

Meet Nuxi · Nuxt Blog Introducing the Nuxt Agent · Nuxt Blog Nuxt 4.4 · Nuxt Blog Nuxt 4.3 · Nuxt Blog Building an MCP Server for Nuxt · Nuxt Blog Nuxt Image v2 · Nuxt Blog Nuxt 4.2 · Nuxt Blog Nuxt UI v4 · Nuxt Blog Nuxt 4.1 · Nuxt Blog Nuxt 3.18 · Nuxt Blog Announcing Nuxt 4.0 · Nuxt Blog Building a Privacy-First Feedback Widget · Nuxt Blog Roadmap to v4 · Nuxt Blog Nuxt 3.17 · Nuxt Blog Nuxt UI v3 · Nuxt Blog Nuxt 3.16 · Nuxt Blog Nuxt 3.15 · Nuxt Blog Introducing Nuxt Icon v1 · Nuxt Blog Nuxt 3.14 · Nuxt Blog Nuxt 3.13 · Nuxt Blog Nuxt 2 End-of-Life (EOL) · Nuxt Blog Nuxt 3.12 · Nuxt Blog Refreshed Nuxt ESLint Integrations · Nuxt Blog Nuxt: Looking forward · Nuxt Blog Nuxt 3.11 · Nuxt Blog The Evolution of Shiki v1.0 · Nuxt Blog Nuxt 3.10 · Nuxt Blog Nuxt 3.9 · Nuxt Blog Nuxt DevTools v1.0 · Nuxt Blog Nuxt 3.8 · Nuxt Blog A New Website · Nuxt Blog Nuxt 3.7 · Nuxt Blog Nuxt on the Edge · Nuxt Blog Nuxt 3.6 · Nuxt Blog Nuxt 3.5 · Nuxt Blog Nuxt 3.4 · Nuxt Blog Introducing Nuxt DevTools · Nuxt Blog Nuxt 3.3 · Nuxt Blog Nuxt: A vision for 2023 · Nuxt Blog Announcing 3.0 · Nuxt Blog Announcing Nuxt 3 Release Candidate · Nuxt Blog Introducing Nuxt 3 Beta · Nuxt Blog Nuxt 2 Static Improvements · Nuxt Blog Going Full Static · Nuxt Blog Understanding how fetch works in Nuxt 2.12 · Nuxt Blog Nuxt 2: From Terminal to Browser · Nuxt Blog Introducing Smart Prefetching · Nuxt Blog Navigation · Nuxt Blog
Introducing Nuxt Scripts · Nuxt Blog
2024-08-20 · via The Nuxt Blog

The Nuxt team, in collaboration with the Chrome Aurora team at Google, is excited to announce the public beta release of Nuxt Scripts.

Nuxt Scripts is a better way to work with third-party scripts, providing improved performance, privacy, security, and developer experience.

Nuxt Scripts Banner

Getting to Nuxt Scripts

Over a year ago, Daniel published the initial Nuxt Scripts RFC. The RFC proposed a module that would "allow third-party scripts to be managed and optimized, following best practices for performant and compliant websites".

Having personal experience with solving performance issues related to third-party scripts, I knew how difficult these performance optimizations could be. Nonetheless, I was keen to tackle the problem and took over the project.

With the RFC as the seed of the idea, I started prototyping what it could look like using Unhead.

Thinking about what I wanted to build exactly, I found that the real issue wasn't just how to load "optimized" third-party scripts but how to make working with third-party scripts a better experience overall.

Why Build a Third-Party Script Module?

94% of sites use at least one third-party provider, with the average site having five third-party providers.

We know that third-party scripts aren't perfect; they slow down the web, cause privacy and security issues, and are a pain to work with.

However, they are fundamentally useful and aren't going anywhere soon.

By exploring the issues with third-party scripts, we can see where improvements can be made.

😒 Developer Experience: A Full-Stack Headache

Let's walk through adding a third-party script to your Nuxt app using a fictional tracker.js script that adds a track function to the window.

We start by loading the script using useHead.

useHead({ script: [{ src: '/tracker.js', defer: true }] })

However, let's now try to get the script functionality working in our app.

The following steps are common when working with third-party scripts in Nuxt:

  • Everything has to be wrapped for SSR safety.
  • Flaky checks for if the script has loaded.
  • Augmenting the window object for types.
<script setup>
// ❌ Oops, window is not defined! 
// 💡 The window can't be directly accessed if we use SSR in Nuxt.
// 👉 We need to make this SSR safe
window.track('page_view', useRoute().path)
</script>

🐌 Performance: "Why can't I get 100 on Lighthouse?"

For a visitor to start interacting with your Nuxt site, the app bundle needs to be downloaded and Vue needs to hydrate the app instance.

Loading third-party scripts can interfere with this hydration process, even when using async or defer. This slows down the network and blocks the main thread, leading to a degraded user experience and poor Core Web Vitals.

The Chrome User Experience Report shows Nuxt sites with numerous third-party resources typically have poorer Interaction to Next Paint (INP) and Largest Contentful Paint (LCP) scores.

To see how third-party scripts degrade performance, we can look at the Web Almanac 2022. The report shows that the top 10 third-party scripts average median blocking time is 1.4 seconds.

🛡️ Privacy & Security: Do no evil?

Of the top 10,000 sites, 58% of them have third-party scripts that exchange tracking IDs stored in external cookies, meaning they can track users across sites even with third-party cookies disabled.

While in many cases our hands are tied with the providers we use, we should try to minimize the amount of our end-users' data that we're leaking where possible.

When we do take on the privacy implications, it can then be difficult to accurately convey these in our privacy policies and build the consent management required to comply with regulations such as GDPR.

Security when using third-party scripts is also a concern. Third-party scripts are common attack vectors for malicious actors, most do not provide integrity hashes for their scripts, meaning they can be compromised and inject malicious code into your app at any time.

What does Nuxt Scripts do about these issues?

Composable: useScript

This composable sits between the <script> tag and the functionality added to window.{thirdPartyKey}.

For the <script> tag, the composable:

  • Gives full visibility into the script's loading and error states
  • Loads scripts as Nuxt is hydrating the app by default, for slightly better performance.
  • Restricts crossorigin and referrerpolicy to improve privacy and security.
  • Provides a way to delay loading the script until you need it.

For the scripts API, it:

  • Provides full type-safety around the script's functions
  • Adds a proxy layer allowing your app to run when the script functions in unsafe contexts (SSR, before the script is loaded, the script is blocked)
const { proxy, onLoaded } = useScript('/hello.js', {
  trigger: 'onNuxtReady',
  use() {
    return window.helloWorld
  }
})

onLoaded(({ greeting }) => {
  // ✅ script is loaded! Hooks into Vue lifecycle
})

// ✅ OR use the proxy API - SSR friendly, called when script is loaded
proxy.greeting() // Hello, World!

declare global {
  interface Window {
    helloWorld: {
      greeting: () => 'Hello World!'
    }
  }
}

Script Registry

The script registry is a collection of first-party integrations for common third-party scripts. As of release, we support 21 scripts, with more to come.

Nuxt Scripts Registry

These registry scripts are fine-tuned wrappers around useScript with full type-safety, runtime validation of the script options (dev only) and environment variable support

For example, we can look at the Fathom Analytics script.

const { proxy } = useScriptFathomAnalytics({
  // ✅ options are validated at runtime
  site: undefined
})
// ✅ typed
proxy.trackPageview()

Facade Components

The registry includes several facade components, such as Google Maps, YouTube and Intercom.

Facade components are "fake" components that get hydrated when the third-party script loads. Facade components have trade-offs but can drastically improve your performance. See the What are Facade Components? guide for more information.

Nuxt Scripts provides facade components as accessible but headless, meaning they are not styled by default but add the necessary a16y data.

Play video

Click to load

Clicking the video will load the YouTube iframe and start the video.

The useScript composable gives you full control over how and when your scripts are loaded, by either providing a custom trigger or manually calling the load() function.

Building on top of this, Nuxt Scripts provides advanced triggers to make it even easier.

  • Consent Management - Load scripts only after the user has given consent such as with a cookie banner.
  • Element Event Triggers - Load scripts based on user interactions such as scrolling, clicking, or form submissions.
const cookieConsentTrigger = useScriptTriggerConsent()
const { proxy } = useScript<{ greeting: () => void }>('/hello.js', {
  // script will only be loaded once the consent has been accepted
  trigger: cookieConsentTrigger
})
// ...
function acceptCookies() {
  cookieConsentTrigger.accept()
}
// greeting() is queued until the user accepts cookies
proxy.greeting()

Bundling Scripts

In many cases, we're loading third-party scripts from a domain that we don't control. This can lead to a number of issues:

  • Privacy: The third-party script can track users across sites.
  • Security: The third-party script can be compromised and inject malicious code.
  • Performance: Extra DNS lookups will slow down the page load.
  • Developer Experience: Consented scripts may be blocked by ad blockers.

To mitigate this, Nuxt Scripts provides a way to bundle third-party scripts into your public directory without any extra work.

useScript('https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js', {
  bundle: true,
})

The script will now be served from /_scripts/{hash} on your own domain.

To be continued

As we saw, there are many opportunities to improve third-party scripts for developers and end-users.

The initial release of Nuxt Scripts has solved some of these issues, but there's still a lot of work ahead of us.

The next items on the roadmap are:

We'd love to have your contribution and support.

Getting started

To get started with Nuxt Scripts, we've created a tutorial to help you get up and running.

Credits

And a big thank you to the early contributors.

Nuxt Scripts Contributors