Nuxt Scriptsのご紹介
Nuxtチームは、GoogleのChrome Auroraチームと協力して、Nuxt Scriptsの公開ベータ版リリースを発表できることを嬉しく思います。
Nuxt Scriptsは、サードパーティースクリプトを扱うためのより優れた方法であり、パフォーマンス、プライバシー、セキュリティ、開発者エクスペリエンスを向上させます。
Nuxt Scriptsへの移行
1年以上前、Danielは最初のNuxt Scripts RFCを発表しました。このRFCは、「パフォーマンスとコンプライアンスに優れたウェブサイトのベストプラクティスに従って、サードパーティースクリプトを管理および最適化する」モジュールを提案しました。
サードパーティースクリプトに関連するパフォーマンスの問題を解決した個人的な経験から、これらのパフォーマンス最適化がいかに難しいかを知っていました。それにもかかわらず、この問題に取り組むことに意欲的で、プロジェクトを引き継ぎました。
RFCをアイデアの種として、Unheadを使用して、それがどのようなものになるかのプロトタイプを作成し始めました。
具体的に何を構築したいかを考えてみると、真の問題は「最適化された」サードパーティースクリプトの読み込み方法ではなく、サードパーティースクリプトの操作全体をどのように改善するかにあることに気づきました。
サードパーティースクリプトモジュールを構築する理由
サイトの94%が少なくとも1つのサードパーティプロバイダーを使用しており、平均的なサイトでは5つのサードパーティプロバイダーを使用しています。
サードパーティースクリプトは完璧ではなく、ウェブの速度を低下させ、プライバシーとセキュリティの問題を引き起こし、操作が困難であることを知っています。
しかし、それらは基本的に有用であり、すぐに消えることはありません。
サードパーティースクリプトの問題点を調査することで、改善できる点が見えてきます。
😒 開発者エクスペリエンス:フルスタックの頭痛
window
オブジェクトにtrack
関数を追加する架空のtracker.js
スクリプトを使用して、サードパーティースクリプトをNuxtアプリに追加する手順を説明します。
useHead
を使用してスクリプトを読み込みます。
useHead({ scripts: [{ src: '/tracker.js', defer: true }] })
しかし、ここでアプリでスクリプトの機能を動作させる方法を試してみましょう。
Nuxtでサードパーティースクリプトを操作する際に一般的になる手順は以下の通りです。
- すべてがSSRの安全性のためにラップされている必要があります。
- スクリプトが読み込まれたかどうかを確認するための不安定なチェック。
- 型のためのwindowオブジェクトの拡張。
<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>
🐌 パフォーマンス:「なぜLighthouseで100点を取れないのか?」
訪問者がNuxtサイトと対話できるようになるには、アプリバンドルをダウンロードし、Vueがアプリインスタンスをハイドレーションする必要があります。
async
またはdefer
を使用する場合でも、サードパーティースクリプトの読み込みは、このハイドレーションプロセスを妨げる可能性があります。これにより、ネットワークの速度が低下し、メインスレッドがブロックされ、ユーザーエクスペリエンスの低下とCore Web Vitalsの悪化につながります。
Chrome User Experience Reportによると、多数のサードパーティリソースを使用するNuxtサイトは、一般的にInteraction to Next Paint (INP)とLargest Contentful Paint (LCP)のスコアが低くなります。
Web Almanac 2022を見ると、サードパーティースクリプトのパフォーマンス低下を確認できます。このレポートによると、上位10個のサードパーティースクリプトの平均中央値ブロッキング時間は1.4秒です。
🛡️ プライバシーとセキュリティ:悪を行わない?
上位10,000サイトのうち、58%が外部Cookieに保存されているトラッキングIDを交換するサードパーティースクリプトを持っており、サードパーティCookieが無効になっている場合でも、サイト間でユーザーを追跡できます。
多くの場合、使用するプロバイダーによって制約を受けていますが、可能な限り、エンドユーザーのデータの漏洩量を最小限に抑えるよう努める必要があります。
プライバシーへの影響に対処する場合、プライバシーポリシーで正確にそれらを伝え、GDPRなどの規制に準拠するために必要な同意管理を構築することが困難になる可能性があります。
サードパーティースクリプトを使用する場合のセキュリティも懸念事項です。サードパーティースクリプトは、悪意のある攻撃者にとって一般的な攻撃ベクトルであり、ほとんどがスクリプトのintegrity
ハッシュを提供していないため、いつでも侵害され、悪意のあるコードがアプリに注入される可能性があります。
Nuxt Scriptsはこれらの問題についてどのように対処しますか?
コンポーザブル:useScript
このコンポーザブルは、<script>
タグとwindow.{thirdPartyKey}
に追加された機能の間にあります。
<script>
タグについて、コンポーザブルは
- スクリプトの読み込みとエラー状態を完全に把握できます。
- デフォルトでNuxtがアプリをハイドレーションする際にスクリプトを読み込むため、パフォーマンスがわずかに向上します。
- プライバシーとセキュリティを向上させるために
crossorigin
とreferrerpolicy
を制限します。 - 必要になるまでスクリプトの読み込みを遅らせる方法を提供します。スクリプトの読み込みを遅らせる
スクリプトAPIについて、
- スクリプトの関数に関する完全な型安全性を提供します。
- プロキシレイヤーを追加することで、スクリプト関数が安全でないコンテキスト(SSR、スクリプトが読み込まれる前、スクリプトがブロックされている)にある場合でも、アプリを実行できます。
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!'
}
}
}
スクリプトレジストリ
スクリプトレジストリは、一般的なサードパーティースクリプトのファーストパーティ統合のコレクションです。リリース時点では、21個のスクリプトをサポートしており、今後さらに追加される予定です。
これらのレジストリスクリプトはuseScript
の微調整されたラッパーであり、完全な型安全性、スクリプトオプションの実行時検証(開発のみ)、および環境変数のサポートが備わっています。
たとえば、Fathom Analyticsスクリプトを確認できます。
const { proxy } = useScriptFathomAnalytics({
// ✅ options are validated at runtime
site: undefined
})
// ✅ typed
proxy.trackPageview()
ファサードコンポーネント
レジストリには、Google Maps、YouTube、Intercomなどのファサードコンポーネントがいくつか含まれています。
ファサードコンポーネントは、サードパーティースクリプトが読み込まれるとハイドレーションされる「偽の」コンポーネントです。ファサードコンポーネントにはトレードオフがありますが、パフォーマンスを大幅に向上させることができます。詳細については、ファサードコンポーネントとは何か?ガイドを参照してください。
Nuxt Scriptsは、ファサードコンポーネントをアクセス可能だがヘッドレスとして提供します。つまり、デフォルトではスタイルが適用されませんが、必要なa16yデータが追加されます。

クリックして読み込む
同意管理と要素イベントトリガー
useScript
コンポーザブルを使用すると、カスタムtrigger
を提供するか、load()
関数を手動で呼び出すことで、スクリプトの読み込み方法とタイミングを完全に制御できます。
これを基盤として、Nuxt Scriptsは、さらに簡単に操作できる高度なトリガーを提供します。
- 同意管理 - Cookieバナーなどを使用して、ユーザーが同意した後にのみスクリプトを読み込みます。
- 要素イベントトリガー - スクロール、クリック、フォーム送信などのユーザー操作に基づいてスクリプトを読み込みます。
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()
スクリプトのバンドル化
多くの場合、制御できないドメインからサードパーティースクリプトを読み込んでいます。これにより、いくつかの問題が発生する可能性があります。
- プライバシー:サードパーティースクリプトは、サイト間でユーザーを追跡できます。
- セキュリティ:サードパーティースクリプトが侵害され、悪意のあるコードが注入される可能性があります。
- パフォーマンス:追加のDNSルックアップにより、ページの読み込み速度が低下します。
- 開発者エクスペリエンス:同意されたスクリプトは、広告ブロッカーによってブロックされる可能性があります。
これを軽減するために、Nuxt Scriptsは、追加の作業なしでサードパーティースクリプトを公開ディレクトリにバンドルする方法を提供します。
useScript('https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js', {
bundle: true,
})
スクリプトは、独自のドメインの/_scripts/{hash}
から提供されるようになります。
続編
ご覧のとおり、開発者とエンドユーザーのためにサードパーティースクリプトを改善する多くの機会があります。
Nuxt Scriptsの最初のリリースでは、これらの問題の一部が解決されましたが、まだ多くの作業が残っています。
ロードマップの次の項目は次のとおりです。
皆様のご貢献とサポートを賜りますようお願い申し上げます。
はじめに
Nuxt Scriptsを使い始めるために、チュートリアルを作成しました。これにより、すぐに使い始めることができます。
クレジット
そして、初期の貢献者の方々に心から感謝いたします。