nuxt logo

Traducción de Documentación (No Oficial)

useNuxtApp

Accede al contexto de ejecución compartido de la aplicación Nuxt.

useNuxtApp es un composable incorporado que proporciona una forma de acceder al contexto de ejecución compartido de Nuxt, también conocido como el contexto de Nuxt, que está disponible tanto en el lado del cliente como en el del servidor (pero no dentro de las rutas de Nitro). Te ayuda a acceder a la instancia de la aplicación Vue, hooks de ejecución, variables de configuración de ejecución y estados internos, como ssrContext y payload.

app.vue
const nuxtApp = useNuxtApp()

Si el contexto de ejecución no está disponible en tu ámbito, useNuxtApp lanzará una excepción cuando se llame. Puedes usar tryUseNuxtApp en su lugar para composables que no requieren nuxtApp, o simplemente para verificar si el contexto está disponible o no sin una excepción.

Métodos

provide (name, value)

nuxtApp es un contexto de ejecución que puedes extender usando plugins de Nuxt. Usa la función provide para crear plugins de Nuxt que hagan valores y métodos auxiliares disponibles en tu aplicación Nuxt a través de todos los composables y componentes.

La función provide acepta los parámetros name y value.

const nuxtApp = useNuxtApp()
nuxtApp.provide('hello', (name) => `Hello ${name}!`)

// Imprime "Hello name!"
console.log(nuxtApp.$hello('name'))

Como puedes ver en el ejemplo anterior, $hello se ha convertido en la nueva y personalizada parte del contexto nuxtApp y está disponible en todos los lugares donde nuxtApp es accesible.

hook(name, cb)

Los hooks disponibles en nuxtApp te permiten personalizar los aspectos de ejecución de tu aplicación Nuxt. Puedes usar hooks de ejecución en composables de Vue.js y plugins de Nuxt para engancharte en el ciclo de vida de renderizado.

La función hook es útil para agregar lógica personalizada al engancharse en el ciclo de vida de renderizado en un punto específico. La función hook se usa principalmente al crear plugins de Nuxt.

Consulta Hooks de Ejecución para ver los hooks de ejecución disponibles llamados por Nuxt.

plugins/test.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('page:start', () => {
    /* tu código va aquí */
  })
  nuxtApp.hook('vue:error', (..._args) => {
    console.log('vue:error')
    // if (import.meta.client) {
    //   console.log(..._args)
    // }
  })
})

callHook(name, ...args)

callHook devuelve una promesa cuando se llama con cualquiera de los hooks existentes.

await nuxtApp.callHook('my-plugin:init')

Propiedades

useNuxtApp() expone las siguientes propiedades que puedes usar para extender y personalizar tu aplicación y compartir estado, datos y variables.

vueApp

vueApp es la instancia de aplicación global de Vue.js a la que puedes acceder a través de nuxtApp.

Algunos métodos útiles:

  • component() - Registra un componente global si se pasa tanto un nombre como una definición de componente, o recupera uno ya registrado si solo se pasa el nombre.
  • directive() - Registra una directiva personalizada global si se pasa tanto un nombre como una definición de directiva, o recupera una ya registrada si solo se pasa el nombre (ejemplo).
  • use() - Instala un Plugin de Vue.js (ejemplo).
Ver también vuejs.org > api > application.html

ssrContext

ssrContext se genera durante el renderizado del lado del servidor y solo está disponible en el lado del servidor.

Nuxt expone las siguientes propiedades a través de ssrContext:

  • url (string) - URL de la solicitud actual.
  • event (evento de solicitud h3js/h3) - Accede a la solicitud y respuesta de la ruta actual.
  • payload (objeto) - Objeto de carga útil de NuxtApp.

payload

payload expone datos y variables de estado del lado del servidor al lado del cliente. Las siguientes claves estarán disponibles en el cliente después de haber sido pasadas desde el lado del servidor:

  • serverRendered (boolean) - Indica si la respuesta está renderizada del lado del servidor.

  • data (objeto) - Cuando obtienes los datos de un endpoint de API usando useFetch o useAsyncData, la carga útil resultante puede ser accedida desde payload.data. Estos datos se almacenan en caché y te ayudan a evitar obtener los mismos datos en caso de que se realice una solicitud idéntica más de una vez.

    const { data } = await useAsyncData('count', () => $fetch('/api/count'))

    Después de obtener el valor de count usando useAsyncData en el ejemplo anterior, si accedes a payload.data, verás { count: 1 } registrado allí.

    Al acceder al mismo payload.data desde ssrcontext, puedes acceder al mismo valor también en el lado del servidor.

  • state (objeto) - Cuando usas el composable useState en Nuxt para establecer un estado compartido, estos datos de estado se acceden a través de payload.state.[nombre-de-tu-estado].

    plugins/my-plugin.ts
    export const useColor = () => useState<string>('color', () => 'pink')
    
    export default defineNuxtPlugin((nuxtApp) => {
      if (import.meta.server) {
        const color = useColor()
      }
    })
    

    También es posible usar tipos más avanzados, como ref, reactive, shallowRef, shallowReactive y NuxtError.

    Desde Nuxt v3.4, es posible definir tu propio reducer/reviver para tipos que no son soportados por Nuxt.

    En el ejemplo a continuación, definimos un reducer (o un serializador) y un reviver (o deserializador) para la clase DateTime de Luxon, usando un plugin de carga útil.

    plugins/date-time-payload.ts
    /**
     * Este tipo de plugin se ejecuta muy temprano en el ciclo de vida de Nuxt, antes de que revivamos la carga útil.
     * No tendrás acceso al enrutador u otras propiedades inyectadas por Nuxt.
     *
     * Ten en cuenta que la cadena "DateTime" es el identificador de tipo y debe
     * ser la misma tanto en el reducer como en el reviver.
     */
    export default definePayloadPlugin((nuxtApp) => {
      definePayloadReducer('DateTime', (value) => {
        return value instanceof DateTime && value.toJSON()
      })
      definePayloadReviver('DateTime', (value) => {
        return DateTime.fromISO(value)
      })
    })
    

isHydrating

Usa nuxtApp.isHydrating (boolean) para verificar si la aplicación Nuxt se está hidratando en el lado del cliente.

components/nuxt-error-boundary.ts
export default defineComponent({
  setup (_props, { slots, emit }) {
    const nuxtApp = useNuxtApp()
    onErrorCaptured((err) => {
      if (import.meta.client && !nuxtApp.isHydrating) {
        // ...
      }
    })
  }
})

runWithContext

Probablemente estés aquí porque recibiste un mensaje de "Instancia de Nuxt no disponible". Por favor, usa este método con moderación y reporta ejemplos que estén causando problemas, para que finalmente pueda resolverse a nivel del framework.

El método runWithContext está destinado a ser usado para llamar a una función y darle un contexto de Nuxt explícito. Normalmente, el contexto de Nuxt se pasa implícitamente y no necesitas preocuparte por esto. Sin embargo, al trabajar con escenarios complejos de async/await en middleware/plugins, puedes encontrarte con instancias donde la instancia actual ha sido desestablecida después de una llamada asíncrona.

middleware/auth.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
  const nuxtApp = useNuxtApp()
  let user
  try {
    user = await fetchUser()
    // el compilador de Vue/Nuxt pierde el contexto aquí debido al bloque try/catch.
  } catch (e) {
    user = null
  }
  if (!user) {
    // aplica el contexto de Nuxt correcto a nuestra llamada `navigateTo`.
    return nuxtApp.runWithContext(() => navigateTo('/auth'))
  }
})

Uso

const result = nuxtApp.runWithContext(() => functionWithContext())
  • functionWithContext: Cualquier función que requiera el contexto de la aplicación Nuxt actual. Este contexto se aplicará correctamente de forma automática.

runWithContext devolverá lo que sea que devuelva functionWithContext.

Una Explicación Más Profunda del Contexto

La API de Composición de Vue.js (y los composables de Nuxt de manera similar) funcionan dependiendo de un contexto implícito. Durante el ciclo de vida, Vue establece la instancia temporal del componente actual (y Nuxt la instancia temporal de nuxtApp) en una variable global y la desestablece en el mismo tick. Al renderizar en el lado del servidor, hay múltiples solicitudes de diferentes usuarios y nuxtApp ejecutándose en un mismo contexto global. Debido a esto, Nuxt y Vue desestablecen inmediatamente esta instancia global para evitar filtrar una referencia compartida entre dos usuarios o componentes.

¿Qué significa esto? La API de Composición y los Composables de Nuxt solo están disponibles durante el ciclo de vida y en el mismo tick antes de cualquier operación asíncrona:

// --- Interno de Vue ---
const _vueInstance = null
const getCurrentInstance = () => _vueInstance
// ---

// Vue / Nuxt establece una variable global que hace referencia al componente actual en _vueInstance al llamar a setup()
async function setup() {
  getCurrentInstance() // Funciona
  await someAsyncOperation() // Vue desestablece el contexto en el mismo tick antes de la operación asíncrona!
  getCurrentInstance() // null
}

La solución clásica para esto es almacenar en caché la instancia actual en la primera llamada a una variable local como const instance = getCurrentInstance() y usarla en la siguiente llamada composable, pero el problema es que cualquier llamada composable anidada ahora necesita aceptar explícitamente la instancia como un argumento y no depender del contexto implícito de la API de composición. Esta es una limitación de diseño con los composables y no un problema en sí.

Para superar esta limitación, Vue hace algunos trabajos detrás de escena al compilar nuestro código de aplicación y restaura el contexto después de cada llamada para <script setup>:

const __instance = getCurrentInstance() // Generado por el compilador de Vue
getCurrentInstance() // ¡Funciona!
await someAsyncOperation() // Vue desestablece el contexto
__restoreInstance(__instance) // Generado por el compilador de Vue
getCurrentInstance() // ¡Todavía funciona!

Para una mejor descripción de lo que Vue realmente hace, consulta unjs/unctx#2 (comentario).

Solución

Aquí es donde runWithContext puede ser usado para restaurar el contexto, de manera similar a cómo funciona <script setup>.

Nuxt usa internamente unjs/unctx para soportar composables de manera similar a Vue para plugins y middleware. Esto permite que composables como navigateTo() funcionen sin pasar directamente nuxtApp a ellos, brindando los beneficios de DX y rendimiento de la API de Composición a todo el framework de Nuxt.

Los composables de Nuxt tienen el mismo diseño que la API de Composición de Vue y, por lo tanto, necesitan una solución similar para hacer mágicamente esta transformación. Consulta unjs/unctx#2 (propuesta), unjs/unctx#4 (implementación de la transformación), y nuxt/framework#3884 (Integración en Nuxt).

Actualmente, Vue solo soporta la restauración de contexto asíncrono para <script setup> para el uso de async/await. En Nuxt, se agregó soporte de transformación para defineNuxtPlugin() y defineNuxtRouteMiddleware(), lo que significa que cuando los usas, Nuxt los transforma automáticamente con restauración de contexto.

Problemas Restantes

La transformación unjs/unctx para restaurar automáticamente el contexto parece tener errores con declaraciones try/catch que contienen await, lo que finalmente necesita ser resuelto para eliminar el requisito de la solución alternativa sugerida anteriormente.

Contexto Asíncrono Nativo

Usando una nueva característica experimental, es posible habilitar el soporte de contexto asíncrono nativo usando Node.js AsyncLocalStorage y el nuevo soporte de unctx para hacer que el contexto asíncrono esté disponible nativamente para cualquier composable asíncrono anidado sin necesidad de una transformación o paso/llamada manual con contexto.

El soporte de contexto asíncrono nativo funciona actualmente en Bun y Node.

Ver también guide > going-further > experimental-features#asynccontext

tryUseNuxtApp

Esta función funciona exactamente igual que useNuxtApp, pero devuelve null si el contexto no está disponible en lugar de lanzar una excepción.

Puedes usarlo para composables que no requieren nuxtApp, o simplemente para verificar si el contexto está disponible o no sin una excepción.

Ejemplo de uso:

composable.ts
export function useStandType() {
  // Siempre funciona en el cliente
  if (tryUseNuxtApp()) {
    return useRuntimeConfig().public.STAND_TYPE
  } else {
    return process.env.STAND_TYPE
  }
}