注册表脚本

了解如何使用注册表脚本简化在 Nuxt 脚本中集成第三方脚本。

注册表脚本通过简化在 Nuxt 脚本中集成第三方脚本,提升开发者体验。

支持的注册表脚本列表,请参见 脚本注册表 列表。

特性

😌 安全初始化

许多第三方脚本需要在加载脚本前初始化一些全局状态,Nuxt 脚本会以优化的方式帮你处理这一过程。

🏎️ 细粒度性能调优

每个注册表脚本都经过优化,以尽可能高效的方式加载脚本功能。

📜 完全类型化

处理第三方脚本通常需要自行处理它们的 API 类型。注册表脚本通过提供预定义类型来缓解这一问题,使你的项目能够享受代码补全和类型安全。

✅ 选项验证

使用 Valibot,注册表脚本自动验证第三方脚本的配置选项,帮助你及早发现并解决配置错误。例如,它们会检查 Cloudflare Web Analytics 的令牌长度。

export const CloudflareWebAnalyticsOptions = object({
  /**
   * Cloudflare Web Analytics 的令牌。
   */
  token: string([minLength(32)]),
  /**
   * Cloudflare Web Analytics 通过重写 History API 的 pushState 函数和监听 onpopstate 自动测量 SPA。
   * 不支持基于哈希的路由器。
   *
   * @default true
   */
  spa: optional(boolean()),
})

出于性能考虑,验证仅在开发时进行。在生产构建中会被 tree-shake 掉。

🤫 运行时配置集成

注册表脚本可以通过 .env 文件配置,允许你不在代码中硬编码脚本选项。

NUXT_PUBLIC_SCRIPTS_CLOUDFLARE_WEB_ANALYTICS_TOKEN=YOUR_TOKEN

使用

在开发环境中禁用

当你想在开发环境中使用暴露的 API 脚本(例如组件内调用 gtag)时,你希望加载一个模拟版本,这样脚本就永远不会真正加载。

你可以通过给注册表脚本提供一个 mock 值来实现。

nuxt.config.ts
export default defineNuxtConfig({
  scripts: {
    registry: {
      googleTagManager: true,
    },
  },
  $development: {
    scripts: {
      registry: {
        googleTagManager: "mock",
      },
    },
  },
})

加载多个相同脚本

你可能有需要使用不同配置加载同一个注册表脚本多次的情况。

默认情况下,它们会去重且只加载一次。要加载同一个脚本的多个实例,可以给脚本提供唯一的 key

const { proxy: gaOne } = useScriptGoogleAnalytics({
  id: 'G-TR58L0EF8P',
})

const { proxy: gaTwo } = useScriptGoogleAnalytics({
  // 不设置 key 会返回第一个脚本实例
  key: 'gtag2',
  id: 'G-1234567890',
})

需要注意的是,当修改 key 时,你使用的环境变量会失效。

例如,将 key 设置为 gtag2,你需要按如下方式提供运行时配置:

export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      scripts: {
        gtag2: {
          id: '', // NUXT_PUBLIC_SCRIPTS_GTAG2_ID
        },
      },
    },
  },
})

使用脚本选项和脚本输入

注册表脚本不会阻止你使用核心的 useScript 功能,你可以通过额外的选项启用高级功能。

import { useTimeout } from '@vueuse/core'
import { useScriptCloudflareWebAnalytics } from '#imports'

const { ready } = useTimeout(5000)
useScriptCloudflareWebAnalytics({
  token: '123',
  // 传递给 script 元素的 HTML 属性
  scriptInput: {
    'data-cf-test': 'true'
  },
  // 用于高级功能的 useScript 选项
  scriptOptions: {
    trigger: ready,
    bundle: true,
  },
})

加载最佳实践

当在多个页面或组件中使用注册表脚本时,建议你在 app.vuenuxt.config 中初始化脚本并传入所需配置。

后续对注册表脚本的调用会使用同一个脚本实例,不需要再次传入选项。

export default defineNuxtConfig({
  scripts: {
    registry: {
      // 加载脚本
      fathomAnalytics: {
        site: 'SITE_ID',
      }
    }
  }
})

或者,你可以将注册表脚本封装成一个 composable 以便更方便地实例化脚本。

export function useFathomAnalytics() {
  return useScriptFathomAnalytics({
    site: 'SITE_ID',
  })
}

扩展脚本注册表

你可以在 nuxt.config.ts 中使用 scripts:registry 钩子扩展脚本注册表:

nuxt.config.ts
import { createResolver } from '@nuxt/kit'

const { resolve } = createResolver(import.meta.url)

export default defineNuxtConfig({
  modules: ['@nuxt/scripts'],

  hooks: {
    'scripts:registry': function (registry) {
      registry.push({
        category: 'custom',
        label: '我的自定义分析',
        logo: '<svg>...</svg>', // 可选
        import: {
          name: 'useScriptMyAnalytics',
          from: resolve('./composables/useScriptMyAnalytics'),
        },
      })
    },
  },

  devtools: {
    enabled: true,
  },
})

然后创建你的自定义脚本 composable:

composables/useScriptMyAnalytics.ts
import { useRegistryScript } from '#nuxt-scripts/utils'
import { object, string } from '#nuxt-scripts-validator'

export interface MyAnalyticsApi {
  track: (event: string, data?: Record<string, any>) => void
  identify: (userId: string) => void
}

// 用于验证和 DevTools 元数据的 Schema
const MyAnalyticsSchema = object({
  apiKey: string(),
})

export function useScriptMyAnalytics<T extends MyAnalyticsApi>(options?: {
  apiKey: string
  scriptOptions?: NuxtUseScriptOptions
}) {
  return useRegistryScript<T, typeof MyAnalyticsSchema>('myAnalytics', () => ({
    scriptInput: {
      src: 'https://analytics.example.com/sdk.js',
    },
    scriptOptions: {
      ...options?.scriptOptions,
      use() {
        // 初始化脚本
        window.MyAnalytics.init(options?.apiKey)
        return window.MyAnalytics as T
      },
    },
  }), options, { schema: MyAnalyticsSchema })
}

使用自定义注册表脚本

注册后,你的自定义脚本使用方式与内置注册表脚本完全相同:

pages/index.vue
<script setup>
// 从注册表自动导入
const { proxy, status } = useScriptMyAnalytics({
  apiKey: 'your-api-key',
  scriptOptions: {
    trigger: 'onNuxtReady'
  }
})

// 使用脚本 API
function trackClick() {
  proxy.track('button_click', { button: 'hero-cta' })
}
</script>

<template>
  <button @click="trackClick">
    跟踪此点击
  </button>
  <div>状态: {{ status }}</div>
</template>

DevTools 集成

当你包含验证 Schema 时,Nuxt 脚本会自动用你的脚本配置填充 DevTools 元数据。在开发模式下,registryKeyregistryMeta 会自动设置,使你能够: