diff --git a/packages/schema/src/script.ts b/packages/schema/src/script.ts index 4d48113b..344718bc 100644 --- a/packages/schema/src/script.ts +++ b/packages/schema/src/script.ts @@ -26,6 +26,7 @@ export interface ScriptInstance { entry?: ActiveHeadEntry load: () => Promise remove: () => boolean + updateTrigger: (trigger: UseScriptOptions['trigger']) => void // cbs onLoaded: (fn: (instance: T) => void | Promise) => void onError: (fn: (err?: Error) => void | Promise) => void diff --git a/packages/unhead/src/composables/useScript.ts b/packages/unhead/src/composables/useScript.ts index 67a1b676..2b5edb7e 100644 --- a/packages/unhead/src/composables/useScript.ts +++ b/packages/unhead/src/composables/useScript.ts @@ -2,7 +2,9 @@ import { ScriptNetworkEvents, hashCode } from '@unhead/shared' import type { AsAsyncFunctionValues, Head, + SchemaAugmentations, ScriptInstance, + Unhead, UseFunctionType, UseScriptInput, UseScriptOptions, @@ -96,6 +98,8 @@ export function useScript = Record>> { instance: (!head.ssr && options?.use?.()) || null, proxy: null, @@ -137,6 +141,11 @@ export function useScript = Record void | Promise) { return _registerCb('error', cb) }, + updateTrigger(trigger: UseScriptOptions['trigger']) { + // cancel previous trigger + triggerAbortController.abort() + handleTrigger(trigger, triggerAbortController, script, head) + }, _cbs, }) as UseScriptContext // script is ready @@ -153,13 +162,8 @@ export function useScript = Record script.load()) + handleTrigger(trigger, triggerAbortController, script, head) // support deprecated behavior script.$script = script const proxyChain = (instance: any, accessor?: string | symbol, accessors?: (string | symbol)[]) => { @@ -211,3 +215,20 @@ export function useScript = Record, head: Unhead>) { + if ((trigger === 'client' && !head.ssr) || trigger === 'server') { + script.load() + } + else if (trigger instanceof Promise) { + new Promise((resolve, reject) => { + trigger.then(script.load).then(resolve) + abortController.signal.addEventListener('abort', reject) + }).catch(() => { + // cancelled + }) + } + else if (typeof trigger === 'function') { + trigger(async () => script.load()) + } +} diff --git a/test/unhead/e2e/scripts.test.ts b/test/unhead/e2e/scripts.test.ts index eee6f755..a6ce6e72 100644 --- a/test/unhead/e2e/scripts.test.ts +++ b/test/unhead/e2e/scripts.test.ts @@ -1,5 +1,5 @@ import { describe, it } from 'vitest' -import { createHead, useHead } from 'unhead' +import { createHead, useHead, useScript } from 'unhead' import { renderSSRHead } from '@unhead/ssr' import { renderDOMHead } from '@unhead/dom' import { useDom } from '../../fixtures' @@ -53,4 +53,24 @@ describe('unhead e2e scripts', () => { " `) }) + + it('expect to update trigger', async () => { + const promise = new Promise(() => {}) + const script = useScript({ + src: 'https://cdn.example.com/script.js', + }, { + trigger: promise, + }) + + const newPromise = new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 25) + }) + expect(script.status).toBe('awaitingLoad') + script.updateTrigger(newPromise) + expect(script.status).toBe('awaitingLoad') + await newPromise + expect(script.status).toBe('loading') + }) })