Hooks
script:updated Hook
On this page
The script:updated
hook is called when a script instance managed by Unhead is updated. This hook is specific to Unhead's script management features and provides a way to react to changes in script status, such as loading, execution, or errors.
Hook Signature
export interface Hook {
'script:updated': (ctx: { script: ScriptInstance<any> }) => void | Promise<void>
}
Parameters
Name | Type | Description |
---|---|---|
ctx | Object | Context object with script information |
ctx.script | ScriptInstance<any> | The script instance that was updated |
Returns
void
or Promise<void>
Usage Example
import { createHead } from 'unhead'
const head = createHead({
hooks: {
'script:updated': (ctx) => {
// Log script status changes
const { script } = ctx
console.log(`Script "${script.id}" updated, status: ${script.status}`)
// React to specific script updates
if (script.id === 'analytics' && script.status === 'loaded') {
console.log('Analytics script has loaded successfully')
}
}
}
})
Use Cases
Script Loading Monitoring
Track script loading status across your application:
import { defineHeadPlugin } from 'unhead'
export const scriptMonitoringPlugin = defineHeadPlugin({
hooks: {
'script:updated': (ctx) => {
const { script } = ctx
// Log detailed script status updates
switch (script.status) {
case 'loading':
console.log(`Script loading started: ${script.id}`)
break
case 'loaded':
console.log(`Script loaded successfully: ${script.id}`)
break
case 'error':
console.error(`Script failed to load: ${script.id}`, script.error)
break
case 'idle':
console.log(`Script waiting: ${script.id}`)
break
}
// Track loading times for performance monitoring
if (script.status === 'loaded' && script.loadStart) {
const loadTime = Date.now() - script.loadStart
console.log(`Script "${script.id}" loaded in ${loadTime}ms`)
// Report to analytics or performance monitoring
if (window.performance && window.performance.mark) {
window.performance.mark(`script-${script.id}-loaded`)
window.performance.measure(
`script-${script.id}-load-time`,
`script-${script.id}-loading`,
`script-${script.id}-loaded`
)
}
}
}
}
})
Dependency Management
Manage script dependencies and trigger actions when scripts load:
import { defineHeadPlugin } from 'unhead'
export const scriptDependencyPlugin = defineHeadPlugin({
hooks: {
'script:updated': (ctx) => {
const { script } = ctx
// Track loaded scripts in a global registry
if (!window.__LOADED_SCRIPTS) {
window.__LOADED_SCRIPTS = new Set()
}
if (script.status === 'loaded') {
// Add to loaded scripts registry
window.__LOADED_SCRIPTS.add(script.id)
// Check for dependency chains
checkDependencies(script.id)
}
}
}
})
// Helper function to check and execute dependent scripts
function checkDependencies(loadedScriptId) {
// Define script dependencies (scripts that depend on others)
const dependencyMap = {
'maps-init': ['google-maps-api'],
'analytics-enhanced': ['analytics-base'],
'shop-components': ['vue', 'shopping-cart-api']
}
// Check if any scripts are waiting for this one
Object.entries(dependencyMap).forEach(([scriptId, dependencies]) => {
if (dependencies.includes(loadedScriptId)) {
// Check if all dependencies for this script are now loaded
const allDepsLoaded = dependencies.every(dep =>
window.__LOADED_SCRIPTS.has(dep)
)
if (allDepsLoaded) {
console.log(`All dependencies loaded for ${scriptId}, initializing...`)
initScript(scriptId)
}
}
})
}
// Helper function to initialize dependent scripts
function initScript(scriptId) {
// This would handle the initialization of scripts that depend on others
console.log(`Initializing dependent script: ${scriptId}`)
// Your actual initialization logic would go here
// For example, you might call a global function that was loaded
if (scriptId === 'maps-init' && window.google && window.google.maps) {
window.initGoogleMaps?.()
}
}
Error Recovery
Implement error recovery strategies for failed scripts:
import { defineHeadPlugin } from 'unhead'
export const scriptErrorRecoveryPlugin = defineHeadPlugin({
hooks: {
'script:updated': (ctx) => {
const { script } = ctx
// Handle script loading errors
if (script.status === 'error') {
console.error(`Script "${script.id}" failed to load:`, script.error)
// Track retry attempts
script.retryCount = (script.retryCount || 0) + 1
// Implement retry strategy with exponential backoff
if (script.retryCount <= 3) {
const backoffTime = 2 ** script.retryCount * 1000
console.log(`Retrying script "${script.id}" in ${backoffTime}ms (attempt ${script.retryCount}/3)`)
setTimeout(() => {
// Reset status and try again
script.status = 'idle'
// Use a different CDN or fallback URL if available
if (script.retryCount > 1 && script.fallbackSrc) {
script.src = script.fallbackSrc
console.log(`Using fallback source for "${script.id}": ${script.fallbackSrc}`)
}
// Trigger reload
script.load()
}, backoffTime)
}
else {
// After max retries, log failure and try to recover app state
console.error(`Script "${script.id}" failed after ${script.retryCount} retry attempts`)
// Notify user if the script was critical
if (script.critical) {
showUserErrorNotification(script.id)
}
// Try to load from local fallback if available
if (script.localFallback) {
console.log(`Loading local fallback for "${script.id}"`)
loadLocalFallback(script.id, script.localFallback)
}
}
}
}
}
})
// Helper functions for error recovery
function showUserErrorNotification(scriptId) {
console.log(`Showing error notification for script: ${scriptId}`)
// Your notification logic
}
function loadLocalFallback(scriptId, fallbackPath) {
console.log(`Loading local fallback for ${scriptId} from ${fallbackPath}`)
// Your fallback loading logic
}
Did this page help you?