From e50f646758f5a48e836523d1976d62e18e2893a4 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Fri, 28 Jul 2023 18:00:53 +0800 Subject: [PATCH] Fix head propagation for MDX components (#7838) --- .changeset/friendly-bulldogs-flash.md | 5 +++ packages/astro/src/@types/astro.ts | 2 -- packages/astro/src/content/runtime.ts | 6 ++-- packages/astro/src/core/render/result.ts | 1 - packages/astro/src/runtime/server/index.ts | 1 - .../runtime/server/render/astro/instance.ts | 10 ++---- .../src/runtime/server/render/astro/render.ts | 5 +-- .../src/runtime/server/render/component.ts | 2 +- .../astro/src/runtime/server/render/index.ts | 2 +- .../astro/src/runtime/server/render/tags.ts | 33 +------------------ 10 files changed, 15 insertions(+), 52 deletions(-) create mode 100644 .changeset/friendly-bulldogs-flash.md diff --git a/.changeset/friendly-bulldogs-flash.md b/.changeset/friendly-bulldogs-flash.md new file mode 100644 index 000000000..88a4c88d3 --- /dev/null +++ b/.changeset/friendly-bulldogs-flash.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix head propagation for MDX components diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 635ef0331..fb34954ac 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -2033,8 +2033,6 @@ export interface SSRMetadata { headInTree: boolean; extraHead: string[]; propagators: Map; - // Used to key track of unique content; links and script tags - contentKeys: Set; } /* Preview server stuff */ diff --git a/packages/astro/src/content/runtime.ts b/packages/astro/src/content/runtime.ts index b125eeaac..fe77524cf 100644 --- a/packages/astro/src/content/runtime.ts +++ b/packages/astro/src/content/runtime.ts @@ -7,7 +7,7 @@ import { createHeadAndContent, renderComponent, renderTemplate, - renderUniqueScriptElement, + renderScriptElement, renderUniqueStylesheet, unescapeHTML, type AstroComponentFactory, @@ -303,9 +303,7 @@ async function render({ .join(''); } if (Array.isArray(collectedScripts)) { - scripts = collectedScripts - .map((script: any) => renderUniqueScriptElement(result, script)) - .join(''); + scripts = collectedScripts.map((script: any) => renderScriptElement(script)).join(''); } let props = baseProps; diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 2bfdb99b0..968b232d4 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -258,7 +258,6 @@ export function createResult(args: CreateResultArgs): SSRResult { headInTree: false, extraHead: [], propagators: new Map(), - contentKeys: new Set(), }, }; diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 0fb85b3ce..aca260d00 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -27,7 +27,6 @@ export { renderSlotToString, renderTemplate, renderToString, - renderUniqueScriptElement, renderUniqueStylesheet, voidElementNames, } from './render/index.js'; diff --git a/packages/astro/src/runtime/server/render/astro/instance.ts b/packages/astro/src/runtime/server/render/astro/instance.ts index 06f2706b3..7502d30a7 100644 --- a/packages/astro/src/runtime/server/render/astro/instance.ts +++ b/packages/astro/src/runtime/server/render/astro/instance.ts @@ -37,6 +37,7 @@ export class AstroComponentInstance { } async init(result: SSRResult) { + if (this.returnValue !== undefined) return this.returnValue; this.returnValue = this.factory(result, this.props, this.slotValues); return this.returnValue; } @@ -72,7 +73,7 @@ function validateComponentProps(props: any, displayName: string) { } } -export async function createAstroComponentInstance( +export function createAstroComponentInstance( result: SSRResult, displayName: string, factory: AstroComponentFactory, @@ -81,16 +82,9 @@ export async function createAstroComponentInstance( ) { validateComponentProps(props, displayName); const instance = new AstroComponentInstance(result, props, slots, factory); - if (isAPropagatingComponent(result, factory) && !result._metadata.propagators.has(factory)) { result._metadata.propagators.set(factory, instance); - // Call component instances that might have head content to be propagated up. - const returnValue = await instance.init(result); - if (isHeadAndContent(returnValue)) { - result._metadata.extraHead.push(returnValue.head); - } } - return instance; } diff --git a/packages/astro/src/runtime/server/render/astro/render.ts b/packages/astro/src/runtime/server/render/astro/render.ts index 0cb7d43fa..0c34ef98d 100644 --- a/packages/astro/src/runtime/server/render/astro/render.ts +++ b/packages/astro/src/runtime/server/render/astro/render.ts @@ -71,12 +71,12 @@ export async function renderToReadableStream( // If the Astro component returns a Response on init, return that response if (templateResult instanceof Response) return templateResult; + let renderedFirstPageChunk = false; + if (isPage) { await bufferHeadContent(result); } - let renderedFirstPageChunk = false; - return new ReadableStream({ start(controller) { const destination: RenderDestination = { @@ -158,6 +158,7 @@ async function bufferHeadContent(result: SSRResult) { if (done) { break; } + // Call component instances that might have head content to be propagated up. const returnValue = await value.init(result); if (isHeadAndContent(returnValue)) { result._metadata.extraHead.push(returnValue.head); diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index dcd4b562c..33de90a26 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -420,7 +420,7 @@ async function renderAstroComponent( props: Record, slots: any = {} ): Promise { - const instance = await createAstroComponentInstance(result, displayName, Component, props, slots); + const instance = createAstroComponentInstance(result, displayName, Component, props, slots); // Eagerly render the component so they are rendered in parallel const chunks: RenderDestinationChunk[] = []; diff --git a/packages/astro/src/runtime/server/render/index.ts b/packages/astro/src/runtime/server/render/index.ts index 4760e07b7..70d63ca60 100644 --- a/packages/astro/src/runtime/server/render/index.ts +++ b/packages/astro/src/runtime/server/render/index.ts @@ -6,6 +6,6 @@ export { renderHTMLElement } from './dom.js'; export { maybeRenderHead, renderHead } from './head.js'; export { renderPage } from './page.js'; export { renderSlot, renderSlotToString, type ComponentSlots } from './slot.js'; -export { renderScriptElement, renderUniqueScriptElement, renderUniqueStylesheet } from './tags.js'; +export { renderScriptElement, renderUniqueStylesheet } from './tags.js'; export type { RenderInstruction } from './types'; export { addAttribute, defineScriptVars, voidElementNames } from './util.js'; diff --git a/packages/astro/src/runtime/server/render/tags.ts b/packages/astro/src/runtime/server/render/tags.ts index 00a734814..f15da6571 100644 --- a/packages/astro/src/runtime/server/render/tags.ts +++ b/packages/astro/src/runtime/server/render/tags.ts @@ -9,45 +9,14 @@ export function renderScriptElement({ props, children }: SSRElement) { }); } -export function renderUniqueScriptElement(result: SSRResult, { props, children }: SSRElement) { - if ( - Array.from(result.scripts).some((s) => { - if (s.props.type === props.type && s.props.src === props.src) { - return true; - } - if (!props.src && s.children === children) return true; - }) - ) - return ''; - const key = `script-${props.type}-${props.src}-${children}`; - if (checkOrAddContentKey(result, key)) return ''; - return renderScriptElement({ props, children }); -} - export function renderUniqueStylesheet(result: SSRResult, sheet: StylesheetAsset) { if (sheet.type === 'external') { if (Array.from(result.styles).some((s) => s.props.href === sheet.src)) return ''; - const key = 'link-external-' + sheet.src; - if (checkOrAddContentKey(result, key)) return ''; - return renderElement('link', { - props: { - rel: 'stylesheet', - href: sheet.src, - }, - children: '', - }); + return renderElement('link', { props: { rel: 'stylesheet', href: sheet.src }, children: '' }); } if (sheet.type === 'inline') { if (Array.from(result.styles).some((s) => s.children.includes(sheet.content))) return ''; - const key = `link-inline-` + sheet.content; - if (checkOrAddContentKey(result, key)) return ''; return renderElement('style', { props: { type: 'text/css' }, children: sheet.content }); } } - -function checkOrAddContentKey(result: SSRResult, key: string): boolean { - if (result._metadata.contentKeys.has(key)) return true; - result._metadata.contentKeys.add(key); - return false; -}