mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 21:55:11 +00:00
feat(nuxt): add onNuxtReady
composable (#9478)
This commit is contained in:
parent
d36d115524
commit
4c4249dc33
19
docs/content/1.docs/3.api/3.utils/on-nuxt-ready.md
Normal file
19
docs/content/1.docs/3.api/3.utils/on-nuxt-ready.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
title: "onNuxtReady"
|
||||||
|
description: The onNuxtReady composable allows running a callback after your app has finished initializing.
|
||||||
|
---
|
||||||
|
|
||||||
|
# `onNuxtReady`
|
||||||
|
|
||||||
|
The `onNuxtReady` composable allows running a callback after your app has finished initializing. It is ideal for running code that should not block the initial rendering of your app.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtPlugin(() => {
|
||||||
|
onNuxtReady(async () => {
|
||||||
|
const myAnalyticsLibrary = await import('my-big-analytics-library')
|
||||||
|
// do something with myAnalyticsLibrary
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
It is 'safe' to run even after your app has initialized. In this case, then the code will be registered to run in the next idle callback.
|
16
packages/nuxt/src/app/compat/idle-callback.ts
Normal file
16
packages/nuxt/src/app/compat/idle-callback.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Polyfills for Safari support
|
||||||
|
// https://caniuse.com/requestidlecallback
|
||||||
|
export const requestIdleCallback: Window['requestIdleCallback'] = process.server
|
||||||
|
? undefined as any
|
||||||
|
: (globalThis.requestIdleCallback || ((cb) => {
|
||||||
|
const start = Date.now()
|
||||||
|
const idleDeadline = {
|
||||||
|
didTimeout: false,
|
||||||
|
timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
|
||||||
|
}
|
||||||
|
return setTimeout(() => { cb(idleDeadline) }, 1)
|
||||||
|
}))
|
||||||
|
|
||||||
|
export const cancelIdleCallback: Window['cancelIdleCallback'] = process.server
|
||||||
|
? null as any
|
||||||
|
: (globalThis.cancelIdleCallback || ((id) => { clearTimeout(id) }))
|
@ -3,8 +3,10 @@ import type { RouteLocationRaw } from 'vue-router'
|
|||||||
import { hasProtocol } from 'ufo'
|
import { hasProtocol } from 'ufo'
|
||||||
|
|
||||||
import { preloadRouteComponents } from '../composables/preload'
|
import { preloadRouteComponents } from '../composables/preload'
|
||||||
|
import { onNuxtReady } from '../composables/ready'
|
||||||
import { navigateTo, useRouter } from '../composables/router'
|
import { navigateTo, useRouter } from '../composables/router'
|
||||||
import { useNuxtApp } from '../nuxt'
|
import { useNuxtApp } from '../nuxt'
|
||||||
|
import { cancelIdleCallback, requestIdleCallback } from '../compat/idle-callback'
|
||||||
|
|
||||||
const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => arg !== undefined)
|
const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => arg !== undefined)
|
||||||
|
|
||||||
@ -42,23 +44,6 @@ export type NuxtLinkProps = {
|
|||||||
ariaCurrentValue?: string
|
ariaCurrentValue?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polyfills for Safari support
|
|
||||||
// https://caniuse.com/requestidlecallback
|
|
||||||
const requestIdleCallback: Window['requestIdleCallback'] = process.server
|
|
||||||
? undefined as any
|
|
||||||
: (globalThis.requestIdleCallback || ((cb) => {
|
|
||||||
const start = Date.now()
|
|
||||||
const idleDeadline = {
|
|
||||||
didTimeout: false,
|
|
||||||
timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
|
|
||||||
}
|
|
||||||
return setTimeout(() => { cb(idleDeadline) }, 1)
|
|
||||||
}))
|
|
||||||
|
|
||||||
const cancelIdleCallback: Window['cancelIdleCallback'] = process.server
|
|
||||||
? null as any
|
|
||||||
: (globalThis.cancelIdleCallback || ((id) => { clearTimeout(id) }))
|
|
||||||
|
|
||||||
export function defineNuxtLink (options: NuxtLinkOptions) {
|
export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||||
const componentName = options.componentName || 'NuxtLink'
|
const componentName = options.componentName || 'NuxtLink'
|
||||||
|
|
||||||
@ -197,7 +182,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
let unobserve: Function | null = null
|
let unobserve: Function | null = null
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const observer = useObserver()
|
const observer = useObserver()
|
||||||
function registerCallback () {
|
onNuxtReady(() => {
|
||||||
idleId = requestIdleCallback(() => {
|
idleId = requestIdleCallback(() => {
|
||||||
if (el?.value?.tagName) {
|
if (el?.value?.tagName) {
|
||||||
unobserve = observer!.observe(el.value, async () => {
|
unobserve = observer!.observe(el.value, async () => {
|
||||||
@ -211,12 +196,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
if (nuxtApp.isHydrating) {
|
|
||||||
nuxtApp.hooks.hookOnce('app:suspense:resolve', registerCallback)
|
|
||||||
} else {
|
|
||||||
registerCallback()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
if (idleId) { cancelIdleCallback(idleId) }
|
if (idleId) { cancelIdleCallback(idleId) }
|
||||||
|
@ -10,6 +10,7 @@ export type { FetchResult, UseFetchOptions } from './fetch'
|
|||||||
export { useCookie } from './cookie'
|
export { useCookie } from './cookie'
|
||||||
export type { CookieOptions, CookieRef } from './cookie'
|
export type { CookieOptions, CookieRef } from './cookie'
|
||||||
export { useRequestHeaders, useRequestEvent, setResponseStatus } from './ssr'
|
export { useRequestHeaders, useRequestEvent, setResponseStatus } from './ssr'
|
||||||
|
export { onNuxtReady } from './ready'
|
||||||
export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, onBeforeRouteLeave, onBeforeRouteUpdate, setPageLayout, navigateTo, useRoute, useRouter } from './router'
|
export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, onBeforeRouteLeave, onBeforeRouteUpdate, setPageLayout, navigateTo, useRoute, useRouter } from './router'
|
||||||
export type { AddRouteMiddlewareOptions, RouteMiddleware } from './router'
|
export type { AddRouteMiddlewareOptions, RouteMiddleware } from './router'
|
||||||
export { preloadComponents, prefetchComponents, preloadRouteComponents } from './preload'
|
export { preloadComponents, prefetchComponents, preloadRouteComponents } from './preload'
|
||||||
|
11
packages/nuxt/src/app/composables/ready.ts
Normal file
11
packages/nuxt/src/app/composables/ready.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { useNuxtApp } from '../nuxt'
|
||||||
|
import { requestIdleCallback } from '../compat/idle-callback'
|
||||||
|
|
||||||
|
export const onNuxtReady = (callback: () => any) => {
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
if (nuxtApp.isHydrating) {
|
||||||
|
nuxtApp.hooks.hookOnce('app:suspense:resolve', () => { requestIdleCallback(callback) })
|
||||||
|
} else {
|
||||||
|
requestIdleCallback(callback)
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,7 @@ const appPreset = defineUnimportPreset({
|
|||||||
'useRequestEvent',
|
'useRequestEvent',
|
||||||
'setResponseStatus',
|
'setResponseStatus',
|
||||||
'setPageLayout',
|
'setPageLayout',
|
||||||
|
'onNuxtReady',
|
||||||
'useRouter',
|
'useRouter',
|
||||||
'useRoute',
|
'useRoute',
|
||||||
'defineNuxtRouteMiddleware',
|
'defineNuxtRouteMiddleware',
|
||||||
|
Loading…
Reference in New Issue
Block a user