2023-02-16 14:40:51 +00:00
|
|
|
import { joinURL, hasProtocol } from 'ufo'
|
2023-03-10 08:01:21 +00:00
|
|
|
import { useHead } from '@unhead/vue'
|
2023-02-09 06:28:58 +00:00
|
|
|
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
|
2022-09-10 13:57:16 +00:00
|
|
|
|
|
|
|
interface LoadPayloadOptions {
|
|
|
|
fresh?: boolean
|
|
|
|
hash?: string
|
|
|
|
}
|
|
|
|
|
2023-03-14 10:09:50 +00:00
|
|
|
export function loadPayload (url: string, opts: LoadPayloadOptions = {}): Record<string, any> | Promise<Record<string, any>> | null {
|
2022-09-10 13:57:16 +00:00
|
|
|
if (process.server) { return null }
|
|
|
|
const payloadURL = _getPayloadURL(url, opts)
|
|
|
|
const nuxtApp = useNuxtApp()
|
|
|
|
const cache = nuxtApp._payloadCache = nuxtApp._payloadCache || {}
|
2023-03-09 18:36:54 +00:00
|
|
|
if (cache[payloadURL]) {
|
|
|
|
return cache[payloadURL]
|
2022-09-10 13:57:16 +00:00
|
|
|
}
|
2023-03-09 18:36:54 +00:00
|
|
|
cache[payloadURL] = _importPayload(payloadURL).then((payload) => {
|
2022-09-10 13:57:16 +00:00
|
|
|
if (!payload) {
|
2023-03-09 18:36:54 +00:00
|
|
|
delete cache[payloadURL]
|
2022-09-10 13:57:16 +00:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
return payload
|
|
|
|
})
|
2023-03-09 18:36:54 +00:00
|
|
|
return cache[payloadURL]
|
2022-09-10 13:57:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function preloadPayload (url: string, opts: LoadPayloadOptions = {}) {
|
|
|
|
const payloadURL = _getPayloadURL(url, opts)
|
|
|
|
useHead({
|
|
|
|
link: [
|
|
|
|
{ rel: 'modulepreload', href: payloadURL }
|
|
|
|
]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- Internal ---
|
|
|
|
|
|
|
|
function _getPayloadURL (url: string, opts: LoadPayloadOptions = {}) {
|
2022-11-03 22:28:13 +00:00
|
|
|
const u = new URL(url, 'http://localhost')
|
|
|
|
if (u.search) {
|
2022-09-10 13:57:16 +00:00
|
|
|
throw new Error('Payload URL cannot contain search params: ' + url)
|
|
|
|
}
|
2023-03-09 18:37:18 +00:00
|
|
|
if (u.host !== 'localhost' || hasProtocol(u.pathname, { acceptRelative: true })) {
|
2023-02-16 16:59:06 +00:00
|
|
|
throw new Error('Payload URL must not include hostname: ' + url)
|
|
|
|
}
|
2022-09-10 13:57:16 +00:00
|
|
|
const hash = opts.hash || (opts.fresh ? Date.now() : '')
|
2022-11-03 22:28:13 +00:00
|
|
|
return joinURL(useRuntimeConfig().app.baseURL, u.pathname, hash ? `_payload.${hash}.js` : '_payload.js')
|
2022-09-10 13:57:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function _importPayload (payloadURL: string) {
|
|
|
|
if (process.server) { return null }
|
|
|
|
const res = await import(/* webpackIgnore: true */ /* @vite-ignore */ payloadURL).catch((err) => {
|
|
|
|
console.warn('[nuxt] Cannot load payload ', payloadURL, err)
|
|
|
|
})
|
|
|
|
return res?.default || null
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isPrerendered () {
|
|
|
|
// Note: Alternative for server is checking x-nitro-prerender header
|
|
|
|
const nuxtApp = useNuxtApp()
|
|
|
|
return !!nuxtApp.payload.prerenderedAt
|
|
|
|
}
|