useNuxtApp
useNuxtApp
は、Nuxtの共有ランタイムコンテキスト(Nuxtコンテキストとも呼ばれる)にアクセスする方法を提供する組み込みコンポーザブルです。これはクライアント側とサーバー側の両方で使用できます(ただし、Nitroルート内では使用できません)。Vueアプリインスタンス、ランタイムフック、ランタイム設定変数、ssrContext
やpayload
などの内部状態にアクセスできます。
<script setup lang="ts">
const nuxtApp = useNuxtApp()
</script>
スコープ内でランタイムコンテキストを使用できない場合、useNuxtApp
を呼び出すと例外がスローされます。nuxtApp
を必要としないコンポーザブルの場合、または例外を発生させずにコンテキストの可用性をチェックする場合は、代わりにtryUseNuxtApp
を使用できます。
メソッド
provide (name, value)
nuxtApp
は、Nuxtプラグインを使用して拡張できるランタイムコンテキストです。provide
関数を使用してNuxtプラグインを作成し、すべてのコンポーザブルとコンポーネントでNuxtアプリケーションで使用できる値とヘルパーメソッドを提供します。
provide
関数は、name
とvalue
のパラメータを受け取ります。
const nuxtApp = useNuxtApp()
nuxtApp.provide('hello', (name) => `Hello ${name}!`)
// Prints "Hello name!"
console.log(nuxtApp.$hello('name'))
上記の例のように、$hello
はnuxtApp
コンテキストの新しいカスタム部分になり、nuxtApp
がアクセス可能なすべての場所で利用可能になります。
hook(name, cb)
nuxtApp
で使用可能なフックにより、Nuxtアプリケーションのランタイム側面をカスタマイズできます。Vue.jsコンポーザブルとNuxtプラグインでランタイムフックを使用して、レンダリングライフサイクルにフックできます。
hook
関数は、特定の時点でレンダリングライフサイクルにフックすることでカスタムロジックを追加するのに役立ちます。hook
関数は、主にNuxtプラグインを作成する際に使用されます。
Nuxtによって呼び出される利用可能なランタイムフックについては、ランタイムフックを参照してください。
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('page:start', () => {
/* your code goes here */
})
nuxtApp.hook('vue:error', (..._args) => {
console.log('vue:error')
// if (import.meta.client) {
// console.log(..._args)
// }
})
})
callHook(name, ...args)
callHook
は、既存のフックのいずれかで呼び出されるとPromiseを返します。
await nuxtApp.callHook('my-plugin:init')
プロパティ
useNuxtApp()
は、アプリの拡張とカスタマイズ、状態、データ、変数の共有に使用できる次のプロパティを公開します。
vueApp
vueApp
は、nuxtApp
を通じてアクセスできるグローバルなVue.js アプリケーションインスタンスです。
いくつかの便利なメソッド
component()
- 名前文字列とコンポーネント定義の両方を渡すとグローバルコンポーネントを登録し、名前のみを渡すと既に登録されているコンポーネントを取得します。directive()
- 名前文字列とディレクティブ定義の両方を渡すとグローバルカスタムディレクティブを登録し、名前のみを渡すと既に登録されているディレクティブを取得します(例)。use()
- Vue.jsプラグイン をインストールします (例)。
ssrContext
ssrContext
はサーバーサイドレンダリング中に生成され、サーバー側でのみ使用できます。
ssrContext
を通じて、Nuxtは次のプロパティを公開します。
url
(文字列) - 現在のリクエストURL。event
(unjs/h3 リクエストイベント) - 現在のルートのリクエストとレスポンスにアクセスします。payload
(オブジェクト) - NuxtAppペイロードオブジェクト。
payload
payload
は、サーバー側からクライアント側にデータと状態変数を公開します。サーバー側から渡された後、クライアント側で次のキーが使用できます。
serverRendered
(ブール値) - レスポンスがサーバーサイドレンダリングされたかどうかを示します。data
(オブジェクト) -useFetch
またはuseAsyncData
を使用してAPIエンドポイントからデータを取得した場合、結果のペイロードはpayload.data
からアクセスできます。このデータはキャッシュされ、同一のリクエストが複数回行われた場合にデータの再取得を防ぎます。<script setup lang="ts"> const { data } = await useAsyncData('count', () => $fetch('/api/count')) </script>
上記の例でuseAsyncData
を使用してcount
の値を取得した後、payload.data
にアクセスすると、{ count: 1 }
が記録されていることがわかります。ssrcontext
から同じpayload.data
にアクセスすると、サーバー側でも同じ値にアクセスできます。state
(オブジェクト) - NuxtでuseState
コンポーザブルを使用して共有状態を設定する場合、この状態データはpayload.state.[name-of-your-state]
からアクセスされます。plugins/my-plugin.tsexport const useColor = () => useState<string>('color', () => 'pink') export default defineNuxtPlugin((nuxtApp) => { if (import.meta.server) { const color = useColor() } })
より高度な型、例えばref
、reactive
、shallowRef
、shallowReactive
、そしてNuxtError
なども使用できます。
Nuxt v3.4以降、Nuxtでサポートされていない型の独自のリデューサー/リバイバーを定義できます。
以下の例では、ペイロードプラグインを使用して、LuxonのDateTimeクラスのリデューサー(またはシリアライザー)とリバイバー(またはデシリアライザー)を定義します。plugins/date-time-payload.ts/** * This kind of plugin runs very early in the Nuxt lifecycle, before we revive the payload. * You will not have access to the router or other Nuxt-injected properties. * * Note that the "DateTime" string is the type identifier and must * be the same on both the reducer and the reviver. */ export default definePayloadPlugin((nuxtApp) => { definePayloadReducer('DateTime', (value) => { return value instanceof DateTime && value.toJSON() }) definePayloadReviver('DateTime', (value) => { return DateTime.fromISO(value) }) })
isHydrating
nuxtApp.isHydrating
(ブール値)を使用して、Nuxtアプリがクライアント側でハイドレーションしているかどうかを確認します。
export default defineComponent({
setup (_props, { slots, emit }) {
const nuxtApp = useNuxtApp()
onErrorCaptured((err) => {
if (import.meta.client && !nuxtApp.isHydrating) {
// ...
}
})
}
})
runWithContext
runWithContext
メソッドは、関数を呼び出して明示的なNuxtコンテキストを与えるために使用することを目的としています。通常、Nuxtコンテキストは暗黙的に渡され、このことを気にする必要はありません。しかし、ミドルウェア/プラグインで複雑なasync
/await
シナリオを扱う場合、非同期呼び出しの後、現在のインスタンスが設定解除されているインスタンスに遭遇する可能性があります。
export default defineNuxtRouteMiddleware(async (to, from) => {
const nuxtApp = useNuxtApp()
let user
try {
user = await fetchUser()
// the Vue/Nuxt compiler loses context here because of the try/catch block.
} catch (e) {
user = null
}
if (!user) {
// apply the correct Nuxt context to our `navigateTo` call.
return nuxtApp.runWithContext(() => navigateTo('/auth'))
}
})
使用方法
const result = nuxtApp.runWithContext(() => functionWithContext())
functionWithContext
: 現在のNuxtアプリケーションのコンテキストを必要とする関数。このコンテキストは自動的に正しく適用されます。
runWithContext
はfunctionWithContext
が返すものを返します。
コンテキストの詳細な説明
Vue.js Composition API(およびNuxtのコンポーザブルも同様)は、暗黙的なコンテキストに依存して動作します。ライフサイクル中に、Vueは現在のコンポーネントの一時的なインスタンス(およびNuxtのnuxtAppの一時的なインスタンス)をグローバル変数に設定し、同じティックで設定解除します。サーバー側でレンダリングする場合、異なるユーザーからの複数のリクエストと、同じグローバルコンテキストで実行されているnuxtAppがあります。このため、NuxtとVueは、2人のユーザーまたはコンポーネント間の共有参照のリークを避けるために、このグローバルインスタンスをすぐに設定解除します。
これは何を意味するのでしょうか?Composition APIとNuxtコンポーザブルは、ライフサイクル中、そして非同期操作の前に同じティックでのみ使用できます。
// --- Vue internal ---
const _vueInstance = null
const getCurrentInstance = () => _vueInstance
// ---
// Vue / Nuxt sets a global variable referencing to current component in _vueInstance when calling setup()
async function setup() {
getCurrentInstance() // Works
await someAsyncOperation() // Vue unsets the context in same tick before async operation!
getCurrentInstance() // null
}
これに対する従来の解決策は、const instance = getCurrentInstance()
のようなローカル変数に最初の呼び出し時に現在のインスタンスをキャッシュし、次のコンポーザブル呼び出しで使用することですが、問題は、ネストされたコンポーザブル呼び出しが、composition-apiの暗黙的なコンテキストに依存せず、インスタンスを明示的に引数として受け入れる必要があることです。これは、コンポーザブルの設計上の制限であり、それ自体が問題ではありません。
この制限を克服するために、Vueはアプリケーションコードのコンパイル時に裏で作業を行い、<script setup>
の各呼び出し後にコンテキストを復元します。
const __instance = getCurrentInstance() // Generated by Vue compiler
getCurrentInstance() // Works!
await someAsyncOperation() // Vue unsets the context
__restoreInstance(__instance) // Generated by Vue compiler
getCurrentInstance() // Still works!
Vueが実際に何をしているかの詳細については、unjs/unctx#2 (comment)を参照してください。
解決策
ここでrunWithContext
を使用して、<script setup>
と同様にコンテキストを復元できます。
Nuxtは内部的にunjs/unctxを使用して、プラグインとミドルウェアのためにVueと同様のコンポーザブルをサポートしています。これにより、nuxtApp
を直接渡すことなくnavigateTo()
のようなコンポーザブルが機能するようになり、Composition APIのDXとパフォーマンスの利点をNuxtフレームワーク全体にもたらします。
NuxtコンポーザブルはVue Composition APIと同じ設計であるため、この変換を魔法のように行うための同様の解決策が必要です。unjs/unctx#2(提案)、unjs/unctx#4(変換の実装)、およびnuxt/framework#3884(Nuxtへの統合)をご覧ください。
現在、Vueは非同期/待機の使用のために<script setup>
の非同期コンテキスト復元のみをサポートしています。Nuxt 3では、defineNuxtPlugin()
とdefineNuxtRouteMiddleware()
の変換サポートが追加されました。つまり、これらを使用すると、Nuxtはコンテキスト復元を使用して自動的に変換します。
残りの問題
コンテキストを自動的に復元するunjs/unctx
変換は、await
を含むtry/catch
ステートメントでバグが発生するようで、最終的には上記で提案された回避策の必要性を排除するために解決する必要があります。
ネイティブ非同期コンテキスト
Node.jsのAsyncLocalStorage
と新しいunctxサポートを使用して、実験的な新機能を使用することで、変換やコンテキストの明示的な受け渡し/呼び出しを必要とせずに、ネイティブに**任意のネストされた非同期コンポーザブル**で非同期コンテキストを使用できます。
tryUseNuxtApp
この関数はuseNuxtApp
とまったく同じように動作しますが、コンテキストが使用できない場合は例外をスローする代わりにnull
を返します。
nuxtApp
を必要としないコンポーザブルに使用したり、例外を発生させることなくコンテキストが使用可能かどうかを確認するだけです。
使用例
export function useStandType() {
// Always works on the client
if (tryUseNuxtApp()) {
return useRuntimeConfig().public.STAND_TYPE
} else {
return process.env.STAND_TYPE
}
}