0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00

improves client:only error message (#10470)

* improves `client:only` error message

* add changeset

* Fix condition for rendering component

* Update rendererAliases in component.ts

* Update changeset
This commit is contained in:
liruifengv 2024-04-03 02:02:07 +08:00 committed by GitHub
parent 16d3f1897a
commit 320c309ca9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 52 additions and 15 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
improves `client:only` error message

View file

@ -32,6 +32,7 @@ import { formatList, internalSpreadAttributes, renderElement, voidElementNames }
const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering');
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();
@ -80,7 +81,7 @@ async function renderFrameworkComponent(
_props: Record<string | number, any>,
slots: any = {}
): Promise<RenderInstance> {
if (!Component && !_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?`
);
@ -164,13 +165,14 @@ 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 = rendererAliases.has(metadata.hydrateArgs)
? rendererAliases.get(metadata.hydrateArgs)
: 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) {
@ -189,13 +191,34 @@ 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 = 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;
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)
@ -241,6 +264,15 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr
}
} else {
if (metadata.hydrate === 'only') {
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(
`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 {
const componentRenderStartTime = performance.now();