Bring back "idle" trigger
enkot opened this issue · comments
Describe the feature
In the latest 1.9.0 release "idle" trigger was removed in favor of user implementation. To me, unhead has always been about simplifying things, and removing "idle" is a step backwards, IMHO.
Now users will be writing something like this or create custom useIdleScript
wrapper, which doesn't make life easier :)
import { waitIdle } from '../utils'
const { $script } = useScript('https://example.com/script.js', {
trigger: waitIdle
})
Can we still have an "idle" trigger with some note in the docs that it doesn't work in all browsers and you can polyfill the requestIdleCallback
?
Additional information
- Would you be willing to help implement this feature?
I do agree with you that it provides a poorer end-user experience, thank you for the feedback.
However, the scope of the useScript
is first and foremost to support high-level integrations and abstractions as a first concern. This requires providing a minimal and solid core to build off of.
For example, in Nuxt, we instead will ship a onNuxtReady
hook which is implemented like so.
export type NuxtUseScriptOptions<T = any> = Omit<UseScriptOptions<T>, 'trigger'> & {
trigger?: UseScriptOptions<T>['trigger'] | 'onNuxtReady'
}
export function useScript<T>(input: UseScriptInput, options?: NuxtUseScriptOptions<T>) {
input = typeof input === 'string' ? { src: input } : input
options = options || {}
if (options.trigger === 'onNuxtReady')
options.trigger = new Promise(resolve => onNuxtReady(resolve))
return _useScript<T>(input, options as any as UseScriptOptions<T>)
}
Using onNuxtReady over idle
is actually important as there's a suspense edge case that this hook takes care of.
You can implement your own useScript
with an idle
hook in the same way.
import { useScript as _useScript, type UseScriptInput } from '@unhead/vue'
import type { UseScriptOptions } from '@unhead/schema'
export function useScript<T>(input: UseScriptInput, options?: Omit<UseScriptOptions<T>, 'trigger'> & {
trigger?: UseScriptOptions<T>['trigger'] | 'idle'
}) {
input = typeof input === 'string' ? { src: input } : input
options = options || {}
if (options.trigger === 'idle')
options.trigger = new Promise(resolve => window.requestIdleCallback(() => resolve()))
return _useScript<T>(input, options as any as UseScriptOptions<T>)
}
I am considering exporting a composable directly from Unhead with the idle callback polyfill as a Promise, at least then it can be tree shaken.
Thank you for the detailed answer.
onNuxtReady
- I see, yes, makes sense to run requestIdleCallback
after suspense:resolve. Looks like insider news about Nuxt 4.0 :)
In general, I understand that this is a difficult question about supporting idle
out of the box, because Safari still does not support it.