mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 05:35:13 +00:00
fix(nuxt): render user-inserted links in island responses (#25219)
This commit is contained in:
parent
84eaf7ba2e
commit
20e88bb171
@ -229,9 +229,8 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for island component rendering
|
// Check for island component rendering
|
||||||
const islandContext = (process.env.NUXT_COMPONENT_ISLANDS && event.path.startsWith('/__nuxt_island'))
|
const isRenderingIsland = (process.env.NUXT_COMPONENT_ISLANDS as unknown as boolean && event.path.startsWith('/__nuxt_island'))
|
||||||
? await getIslandContext(event)
|
const islandContext = isRenderingIsland ? await getIslandContext(event) : undefined
|
||||||
: undefined
|
|
||||||
|
|
||||||
if (import.meta.prerender && islandContext && event.path && await islandCache!.hasItem(event.path)) {
|
if (import.meta.prerender && islandContext && event.path && await islandCache!.hasItem(event.path)) {
|
||||||
return islandCache!.getItem(event.path) as Promise<Partial<RenderResponse>>
|
return islandCache!.getItem(event.path) as Promise<Partial<RenderResponse>>
|
||||||
@ -241,7 +240,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
let url = ssrError?.url as string || islandContext?.url || event.path
|
let url = ssrError?.url as string || islandContext?.url || event.path
|
||||||
|
|
||||||
// Whether we are rendering payload route
|
// Whether we are rendering payload route
|
||||||
const isRenderingPayload = PAYLOAD_URL_RE.test(url) && !islandContext
|
const isRenderingPayload = PAYLOAD_URL_RE.test(url) && !isRenderingIsland
|
||||||
if (isRenderingPayload) {
|
if (isRenderingPayload) {
|
||||||
url = url.substring(0, url.lastIndexOf('/')) || '/'
|
url = url.substring(0, url.lastIndexOf('/')) || '/'
|
||||||
|
|
||||||
@ -260,7 +259,9 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
})
|
})
|
||||||
// needed for hash hydration plugin to work
|
// needed for hash hydration plugin to work
|
||||||
const headEntryOptions: HeadEntryOptions = { mode: 'server' }
|
const headEntryOptions: HeadEntryOptions = { mode: 'server' }
|
||||||
head.push(appHead, headEntryOptions)
|
if (!isRenderingIsland) {
|
||||||
|
head.push(appHead, headEntryOptions)
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize ssr context
|
// Initialize ssr context
|
||||||
const ssrContext: NuxtSSRContext = {
|
const ssrContext: NuxtSSRContext = {
|
||||||
@ -270,7 +271,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
noSSR:
|
noSSR:
|
||||||
!!(process.env.NUXT_NO_SSR) ||
|
!!(process.env.NUXT_NO_SSR) ||
|
||||||
event.context.nuxt?.noSSR ||
|
event.context.nuxt?.noSSR ||
|
||||||
(routeOptions.ssr === false && !islandContext) ||
|
(routeOptions.ssr === false && !isRenderingIsland) ||
|
||||||
(import.meta.prerender ? PRERENDER_NO_SSR_ROUTES.has(url) : false),
|
(import.meta.prerender ? PRERENDER_NO_SSR_ROUTES.has(url) : false),
|
||||||
head,
|
head,
|
||||||
error: !!ssrError,
|
error: !!ssrError,
|
||||||
@ -281,7 +282,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Whether we are prerendering route
|
// Whether we are prerendering route
|
||||||
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !ssrContext.noSSR && !islandContext
|
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !ssrContext.noSSR && !isRenderingIsland
|
||||||
const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(useRuntimeConfig().app.baseURL, url, process.env.NUXT_JSON_PAYLOADS ? '_payload.json' : '_payload.js') : undefined
|
const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(useRuntimeConfig().app.baseURL, url, process.env.NUXT_JSON_PAYLOADS ? '_payload.json' : '_payload.js') : undefined
|
||||||
if (import.meta.prerender) {
|
if (import.meta.prerender) {
|
||||||
ssrContext.payload.prerenderedAt = Date.now()
|
ssrContext.payload.prerenderedAt = Date.now()
|
||||||
@ -330,7 +331,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
await payloadCache!.setItem(withoutTrailingSlash(url), renderPayloadResponse(ssrContext))
|
await payloadCache!.setItem(withoutTrailingSlash(url), renderPayloadResponse(ssrContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NUXT_INLINE_STYLES && !islandContext) {
|
if (process.env.NUXT_INLINE_STYLES && !isRenderingIsland) {
|
||||||
const source = ssrContext.modules ?? ssrContext._registeredComponents
|
const source = ssrContext.modules ?? ssrContext._registeredComponents
|
||||||
if (source) {
|
if (source) {
|
||||||
for (const id of await getEntryIds()) {
|
for (const id of await getEntryIds()) {
|
||||||
@ -340,7 +341,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render inline styles
|
// Render inline styles
|
||||||
const inlinedStyles = (process.env.NUXT_INLINE_STYLES || Boolean(islandContext))
|
const inlinedStyles = (process.env.NUXT_INLINE_STYLES || isRenderingIsland)
|
||||||
? await renderInlineStyles(ssrContext.modules ?? ssrContext._registeredComponents ?? [])
|
? await renderInlineStyles(ssrContext.modules ?? ssrContext._registeredComponents ?? [])
|
||||||
: []
|
: []
|
||||||
|
|
||||||
@ -349,7 +350,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
// Setup head
|
// Setup head
|
||||||
const { styles, scripts } = getRequestDependencies(ssrContext, renderer.rendererContext)
|
const { styles, scripts } = getRequestDependencies(ssrContext, renderer.rendererContext)
|
||||||
// 1.Extracted payload preloading
|
// 1.Extracted payload preloading
|
||||||
if (_PAYLOAD_EXTRACTION) {
|
if (_PAYLOAD_EXTRACTION && !isRenderingIsland) {
|
||||||
head.push({
|
head.push({
|
||||||
link: [
|
link: [
|
||||||
process.env.NUXT_JSON_PAYLOADS
|
process.env.NUXT_JSON_PAYLOADS
|
||||||
@ -361,14 +362,18 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
|
|
||||||
// 2. Styles
|
// 2. Styles
|
||||||
head.push({ style: inlinedStyles })
|
head.push({ style: inlinedStyles })
|
||||||
head.push({
|
if (!isRenderingIsland || import.meta.dev) {
|
||||||
link: Object.values(styles)
|
const link = []
|
||||||
.map(resource =>
|
for (const style in styles) {
|
||||||
({ rel: 'stylesheet', href: renderer.rendererContext.buildAssetsURL(resource.file) })
|
const resource = styles[style]
|
||||||
)
|
if (!import.meta.dev || (resource.file.includes('scoped') && !resource.file.includes('pages/'))) {
|
||||||
}, headEntryOptions)
|
link.push({ rel: 'stylesheet', href: renderer.rendererContext.buildAssetsURL(resource.file) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
head.push({ link }, headEntryOptions)
|
||||||
|
}
|
||||||
|
|
||||||
if (!NO_SCRIPTS) {
|
if (!NO_SCRIPTS && !isRenderingIsland) {
|
||||||
// 3. Resource Hints
|
// 3. Resource Hints
|
||||||
// TODO: add priorities based on Capo
|
// TODO: add priorities based on Capo
|
||||||
head.push({
|
head.push({
|
||||||
@ -395,7 +400,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. Scripts
|
// 5. Scripts
|
||||||
if (!routeOptions.experimentalNoScripts) {
|
if (!routeOptions.experimentalNoScripts && !isRenderingIsland) {
|
||||||
head.push({
|
head.push({
|
||||||
script: Object.values(scripts).map(resource => (<Script> {
|
script: Object.values(scripts).map(resource => (<Script> {
|
||||||
type: resource.module ? 'module' : null,
|
type: resource.module ? 'module' : null,
|
||||||
@ -411,7 +416,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
|
|
||||||
// Create render context
|
// Create render context
|
||||||
const htmlContext: NuxtRenderHTMLContext = {
|
const htmlContext: NuxtRenderHTMLContext = {
|
||||||
island: Boolean(islandContext),
|
island: isRenderingIsland,
|
||||||
htmlAttrs: htmlAttrs ? [htmlAttrs] : [],
|
htmlAttrs: htmlAttrs ? [htmlAttrs] : [],
|
||||||
head: normalizeChunks([headTags, ssrContext.styles]),
|
head: normalizeChunks([headTags, ssrContext.styles]),
|
||||||
bodyAttrs: bodyAttrs ? [bodyAttrs] : [],
|
bodyAttrs: bodyAttrs ? [bodyAttrs] : [],
|
||||||
@ -424,16 +429,15 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
await nitroApp.hooks.callHook('render:html', htmlContext, { event })
|
await nitroApp.hooks.callHook('render:html', htmlContext, { event })
|
||||||
|
|
||||||
// Response for component islands
|
// Response for component islands
|
||||||
if (process.env.NUXT_COMPONENT_ISLANDS && islandContext) {
|
if (isRenderingIsland && islandContext) {
|
||||||
const islandHead: NuxtIslandResponse['head'] = {
|
const islandHead: NuxtIslandResponse['head'] = {
|
||||||
link: [],
|
link: [],
|
||||||
style: []
|
style: []
|
||||||
}
|
}
|
||||||
for (const tag of await head.resolveTags()) {
|
for (const tag of await head.resolveTags()) {
|
||||||
if (tag.tag === 'link' && tag.props.rel === 'stylesheet' && tag.props.href.includes('scoped') && !tag.props.href.includes('pages/')) {
|
if (tag.tag === 'link') {
|
||||||
islandHead.link.push({ ...tag.props, key: 'island-link-' + hash(tag.props.href) })
|
islandHead.link.push({ key: 'island-link-' + hash(tag.props), ...tag.props })
|
||||||
}
|
} else if (tag.tag === 'style' && tag.innerHTML) {
|
||||||
if (tag.tag === 'style' && tag.innerHTML) {
|
|
||||||
islandHead.style.push({ key: 'island-style-' + hash(tag.innerHTML), innerHTML: tag.innerHTML })
|
islandHead.style.push({ key: 'island-style-' + hash(tag.innerHTML), innerHTML: tag.innerHTML })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
|||||||
const serverDir = join(rootDir, '.output/server')
|
const serverDir = join(rootDir, '.output/server')
|
||||||
|
|
||||||
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"200k"`)
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"201k"`)
|
||||||
|
|
||||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1335k"`)
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1335k"`)
|
||||||
|
Loading…
Reference in New Issue
Block a user