mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 13:45:18 +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 { preloadRouteComponents } from '../composables/preload'
|
||||
import { onNuxtReady } from '../composables/ready'
|
||||
import { navigateTo, useRouter } from '../composables/router'
|
||||
import { useNuxtApp } from '../nuxt'
|
||||
import { cancelIdleCallback, requestIdleCallback } from '../compat/idle-callback'
|
||||
|
||||
const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => arg !== undefined)
|
||||
|
||||
@ -42,23 +44,6 @@ export type NuxtLinkProps = {
|
||||
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) {
|
||||
const componentName = options.componentName || 'NuxtLink'
|
||||
|
||||
@ -197,7 +182,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
let unobserve: Function | null = null
|
||||
onMounted(() => {
|
||||
const observer = useObserver()
|
||||
function registerCallback () {
|
||||
onNuxtReady(() => {
|
||||
idleId = requestIdleCallback(() => {
|
||||
if (el?.value?.tagName) {
|
||||
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(() => {
|
||||
if (idleId) { cancelIdleCallback(idleId) }
|
||||
|
@ -10,6 +10,7 @@ export type { FetchResult, UseFetchOptions } from './fetch'
|
||||
export { useCookie } from './cookie'
|
||||
export type { CookieOptions, CookieRef } from './cookie'
|
||||
export { useRequestHeaders, useRequestEvent, setResponseStatus } from './ssr'
|
||||
export { onNuxtReady } from './ready'
|
||||
export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, onBeforeRouteLeave, onBeforeRouteUpdate, setPageLayout, navigateTo, useRoute, useRouter } from './router'
|
||||
export type { AddRouteMiddlewareOptions, RouteMiddleware } from './router'
|
||||
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',
|
||||
'setResponseStatus',
|
||||
'setPageLayout',
|
||||
'onNuxtReady',
|
||||
'useRouter',
|
||||
'useRoute',
|
||||
'defineNuxtRouteMiddleware',
|
||||
|
Loading…
Reference in New Issue
Block a user