From afdb78d650a589ee8a749cab264b6232f0877963 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Mon, 18 Mar 2024 16:16:05 +0800 Subject: [PATCH 1/5] improves `client:only` error message --- .../src/runtime/server/render/component.ts | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index 3fcb6f2aa39a..a35a905de270 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -31,7 +31,7 @@ import { renderSlotToString, renderSlots, type ComponentSlots } from './slot.js' import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js'; const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering'); -const rendererAliases = new Map([['solid', 'solid-js']]); +const clientOnlyValues = new Set(['solid-js', 'solid', 'react', 'preact', 'vue', 'svelte', 'lit']); function guessRenderers(componentUrl?: string): string[] { const extname = componentUrl?.split('.').pop(); @@ -79,7 +79,7 @@ async function renderFrameworkComponent( _props: Record, slots: any = {} ): Promise { - if (!Component && !_props['client:only']) { + if (!Component && !_props['client:only'] && _props['client:only'] !== "") { throw new Error( `Unable to render ${displayName} because it is ${Component}!\nDid you forget to import the component or is it possible there is a typo?` ); @@ -163,13 +163,12 @@ async function renderFrameworkComponent( } else { // Attempt: use explicitly passed renderer name if (metadata.hydrateArgs) { - const passedName = metadata.hydrateArgs; - const rendererName = rendererAliases.has(passedName) - ? rendererAliases.get(passedName) - : passedName; - renderer = renderers.find( - ({ name }) => name === `@astrojs/${rendererName}` || name === rendererName - ); + const rendererName = metadata.hydrateArgs; + if (clientOnlyValues.has(rendererName)) { + renderer = renderers.find( + ({ name }) => name === `@astrojs/${rendererName}` || name === rendererName + ); + } } // Attempt: user only has a single renderer, default to that if (!renderer && validRenderers.length === 1) { @@ -187,13 +186,32 @@ async function renderFrameworkComponent( // If no one claimed the renderer if (!renderer) { if (metadata.hydrate === 'only') { - throw new AstroError({ - ...AstroErrorData.NoClientOnlyHint, - message: AstroErrorData.NoClientOnlyHint.message(metadata.displayName), - hint: AstroErrorData.NoClientOnlyHint.hint( - probableRendererNames.map((r) => r.replace('@astrojs/', '')).join('|') - ), - }); + const rendererName = metadata.hydrateArgs; + if (clientOnlyValues.has(rendererName)) { + // throw an error if provide correct client:only directive but not find the renderer + const plural = validRenderers.length > 1; + throw new AstroError({ + ...AstroErrorData.NoMatchingRenderer, + message: AstroErrorData.NoMatchingRenderer.message( + metadata.displayName, + metadata?.componentUrl?.split('.').pop(), + plural, + validRenderers.length + ), + hint: AstroErrorData.NoMatchingRenderer.hint( + formatList(probableRendererNames.map((r) => '`' + r + '`')) + ), + }); + } else { + // throw an error if an invalid hydration directive was provided + throw new AstroError({ + ...AstroErrorData.NoClientOnlyHint, + message: AstroErrorData.NoClientOnlyHint.message(metadata.displayName), + hint: AstroErrorData.NoClientOnlyHint.hint( + probableRendererNames.map((r) => r.replace('@astrojs/', '')).join('|') + ), + }); + } } else if (typeof Component !== 'string') { const matchingRenderers = validRenderers.filter((r) => probableRendererNames.includes(r.name) @@ -239,6 +257,13 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr } } else { if (metadata.hydrate === 'only') { + const rendererName = metadata.hydrateArgs; + if (!clientOnlyValues.has(rendererName)) { + // warning if provide incorrect client:only directive but find the renderer by guess + console.warn( + `The client:only directive for ${metadata.displayName} is not recognized. The renderer ${renderer.name} will be used. If you intended to use a different renderer, please provide a valid client:only directive.` + ); + } html = await renderSlotToString(result, slots?.fallback); } else { ({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call( From e74a637297b359e3210006159bca26b53337ae6f Mon Sep 17 00:00:00 2001 From: liruifengv Date: Mon, 18 Mar 2024 16:20:33 +0800 Subject: [PATCH 2/5] add changeset --- .changeset/calm-hotels-kiss.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/calm-hotels-kiss.md diff --git a/.changeset/calm-hotels-kiss.md b/.changeset/calm-hotels-kiss.md new file mode 100644 index 000000000000..0fda76962ed2 --- /dev/null +++ b/.changeset/calm-hotels-kiss.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +improves `client:only error` message From 588f1eed76a80145ee7e7d202ecb05b477bec95a Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 20 Mar 2024 11:31:37 +0800 Subject: [PATCH 3/5] Fix condition for rendering component --- packages/astro/src/runtime/server/render/component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index 70a806e8289a..84af5d348d73 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -80,7 +80,7 @@ async function renderFrameworkComponent( _props: Record, slots: any = {} ): Promise { - if (!Component && !_props['client:only'] && _props['client:only'] !== "") { + if (!Component && "client:only" in _props === false) { throw new Error( `Unable to render ${displayName} because it is ${Component}!\nDid you forget to import the component or is it possible there is a typo?` ); From 05dcfd6a7ac4d9a429542493dbf844767478c37c Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 20 Mar 2024 12:26:01 +0800 Subject: [PATCH 4/5] Update rendererAliases in component.ts --- .../astro/src/runtime/server/render/component.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index 84af5d348d73..f16e4cca472f 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -31,7 +31,8 @@ import { type ComponentSlots, renderSlotToString, renderSlots } from './slot.js' import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js'; const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering'); -const clientOnlyValues = new Set(['solid-js', 'solid', 'react', 'preact', 'vue', 'svelte', 'lit']); +const rendererAliases = new Map([['solid', 'solid-js']]); +const clientOnlyValues = new Set(['solid-js', 'react', 'preact', 'vue', 'svelte', 'lit']); function guessRenderers(componentUrl?: string): string[] { const extname = componentUrl?.split('.').pop(); @@ -164,7 +165,9 @@ async function renderFrameworkComponent( } else { // Attempt: use explicitly passed renderer name if (metadata.hydrateArgs) { - const rendererName = metadata.hydrateArgs; + const rendererName = rendererAliases.has(metadata.hydrateArgs) + ? rendererAliases.get(metadata.hydrateArgs) + : metadata.hydrateArgs; if (clientOnlyValues.has(rendererName)) { renderer = renderers.find( ({ name }) => name === `@astrojs/${rendererName}` || name === rendererName @@ -188,7 +191,9 @@ async function renderFrameworkComponent( // If no one claimed the renderer if (!renderer) { if (metadata.hydrate === 'only') { - const rendererName = metadata.hydrateArgs; + const rendererName = rendererAliases.has(metadata.hydrateArgs) + ? rendererAliases.get(metadata.hydrateArgs) + : metadata.hydrateArgs; if (clientOnlyValues.has(rendererName)) { // throw an error if provide correct client:only directive but not find the renderer const plural = validRenderers.length > 1; @@ -259,7 +264,9 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr } } else { if (metadata.hydrate === 'only') { - const rendererName = metadata.hydrateArgs; + const rendererName = rendererAliases.has(metadata.hydrateArgs) + ? rendererAliases.get(metadata.hydrateArgs) + : metadata.hydrateArgs; if (!clientOnlyValues.has(rendererName)) { // warning if provide incorrect client:only directive but find the renderer by guess console.warn( From cb7a7656bcad6b0412450dd54e44cbb2c0850cae Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 20 Mar 2024 12:30:53 +0800 Subject: [PATCH 5/5] Update changeset --- .changeset/calm-hotels-kiss.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/calm-hotels-kiss.md b/.changeset/calm-hotels-kiss.md index 0fda76962ed2..4b565fd9e3ea 100644 --- a/.changeset/calm-hotels-kiss.md +++ b/.changeset/calm-hotels-kiss.md @@ -2,4 +2,4 @@ "astro": patch --- -improves `client:only error` message +improves `client:only` error message