关键概念
useScript 组合式函数是 Nuxt Scripts 的核心,用于加载所有脚本。
在 useScript 之上构建了额外的抽象层,使得以不同方式加载脚本变得更加容易。
Unhead 抽象层
Nuxt Scripts 的 useScript 组合式函数是对 Unhead 的 useScript 的抽象,而后者又是基于 useHead 的抽象。通过 useHead 可用的许多功能,在 Nuxt Scripts 的 useScript 中也能使用。
脚本单例
在 Nuxt Scripts 中,不可能多次加载相同 src(或 key)的脚本。这是因为脚本是全局加载的,并且在所有组件间共享。
这意味着脚本只会经过一次初始化过程,后续对 useScript 的调用都会返回同一实例。
因此,你可以考虑将 useScript 调用封装在自己的组合式函数中,以便更方便地实例化该脚本。
export function useMyScript() {
return useScript({
src: 'https://example.com/script.js',
})
}
默认行为
Nuxt Scripts 不会在 SSR 响应中插入脚本标签。这是一个性能决策,旨在最大限度地减少对 hydration 过程的干扰。相反,脚本默认会在 Nuxt 完全在客户端完成 hydration 后加载。
你可以通过修改 defaultScriptOptions 来改变此行为。
Nuxt Scripts 还会向 <script> 标签插入若干额外的属性,以优化性能和隐私。
async- 脚本异步加载,防止阻塞页面渲染。defer- 脚本延迟执行,确保按加载顺序执行。crossorigin="anonymous"- 脚本带有anonymous属性,防止访问 Cookie。referrerpolicy="no-referrer"- 脚本使用no-referrer策略,防止发送 Referer 头。fetchpriority="low"- 脚本以较低优先级加载,提升页面性能。
注意: 默认不使用
async,而是使用defer。如果需要async,你可以显式禁用defer。
理解代理函数
你可能会好奇 useScript 组合式函数如何返回 SSR 安全的函数,并且可以在脚本加载前调用。
const { proxy } = useScript('/script.js')
// 如你所愿地工作 —— 魔法吗?
proxy.gtag('event', 'page_view')
gtag 函数调用是一个代理,函数会被排队,等脚本加载后才执行。如果脚本从未加载,则函数不会被调用。
这带来了几个优点:
- SSR 安全
- 如果脚本未加载(被广告拦截器阻止),不会破坏你的网站
- 允许随时加载脚本,无需担心脚本和函数调用的顺序
但也有一些缺点:
- 仅适用于不需要返回值的函数。你可以等待函数调用来获取返回值,但这会阻塞页面渲染。
- 如果不了解其工作原理,调试时可能会感到困惑。
如果你想直接访问脚本的 API,建议等待脚本加载完成后再调用。
const { onLoaded } = useScript('/script.js')
// 直接使用脚本实例,而非代理
onLoaded(({ gtag }) => {
gtag('event', 'page_view')
})