diff --git a/.changeset/chatty-knives-confess.md b/.changeset/chatty-knives-confess.md new file mode 100644 index 0000000000..7f07eb893c --- /dev/null +++ b/.changeset/chatty-knives-confess.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Removes the misleading log message telling that a custom renderer is not recognized while it clearly is and works. diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index eedbcbee12..b3979f8317 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -260,15 +260,6 @@ 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(); diff --git a/packages/astro/test/custom-renderer.test.js b/packages/astro/test/custom-renderer.test.js new file mode 100644 index 0000000000..84f03373ce --- /dev/null +++ b/packages/astro/test/custom-renderer.test.js @@ -0,0 +1,42 @@ +import assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Custom Renderer - SSR', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/custom-renderer/', + }); + }); + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('renders /', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + assert.equal($('h1').text(), 'Client Directives'); + }); + + it('renders SSR custom renderer functional components as expected', async () => { + const res = await fixture.fetch('/'); + assert.equal(res.status, 200); + + const html = await res.text(); + const $ = cheerio.load(html); + + assert.equal($('p').length, 5); + }); + }); +}); diff --git a/packages/astro/test/fixtures/custom-renderer/astro.config.mjs b/packages/astro/test/fixtures/custom-renderer/astro.config.mjs new file mode 100644 index 0000000000..54985f8b53 --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/astro.config.mjs @@ -0,0 +1,9 @@ +import { defineConfig } from 'astro/config'; + +// in a real-world scenario, this would be provided a separate package +import customRenderer from './src/custom-renderer'; + +// https://astro.build/config +export default defineConfig({ + integrations: [customRenderer()] +}); diff --git a/packages/astro/test/fixtures/custom-renderer/package.json b/packages/astro/test/fixtures/custom-renderer/package.json new file mode 100644 index 0000000000..5e14cccbc4 --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/package.json @@ -0,0 +1,11 @@ +{ + "name": "@test/custom-renderer", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + }, + "scripts": { + "dev": "astro dev" + } +} diff --git a/packages/astro/test/fixtures/custom-renderer/src/components/CustomRendererTest.ts b/packages/astro/test/fixtures/custom-renderer/src/components/CustomRendererTest.ts new file mode 100644 index 0000000000..f09c6ef751 --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/src/components/CustomRendererTest.ts @@ -0,0 +1,10 @@ +export interface Props { + msg: string; +} + +export default function CustomRendererTest({ msg }: Props) { + return { + tag: "p", + text: msg + } +} \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/client.ts b/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/client.ts new file mode 100644 index 0000000000..b1757fc937 --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/client.ts @@ -0,0 +1,25 @@ +export default (parentElement: HTMLElement) => + + async ( + Component: any, + props: Record, + //{ default: children, ...slotted }: Record, + //{ client }: Record, + ) => { + + // in a real-world scenario, this would be a more complex function + // actually rendering the components return value (which might be an AST/VDOM) + + const vdom = Component(props); + + const node: Node = document.createElement(vdom.tag); + node.textContent = `${vdom.text} (rendered by client.ts)`; + parentElement.appendChild(node); + + // cleanup + parentElement.addEventListener('astro:unmount', () => { + if (node.parentNode) { + node.parentNode.removeChild(node); + } + }, { once: true }); + }; \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/index.ts b/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/index.ts new file mode 100644 index 0000000000..2c8654994c --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/index.ts @@ -0,0 +1,23 @@ +import type { AstroIntegration, AstroRenderer, ContainerRenderer } from 'astro'; + +const getRenderer = (): AstroRenderer => ({ + name: 'custom-renderer', + clientEntrypoint: '@custom-renderer/client', + serverEntrypoint: '@custom-renderer/server', +}) + +export const getContainerRenderer = (): ContainerRenderer => ({ + name: 'custom-renderer', + serverEntrypoint: '@custom-renderer/server', +}) + +export default function (): AstroIntegration { + return { + name: 'custom-renderer', + hooks: { + 'astro:config:setup': ({ addRenderer }) => { + addRenderer(getRenderer()); + }, + }, + }; +} \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/server.ts b/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/server.ts new file mode 100644 index 0000000000..e3436c4ce2 --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/src/custom-renderer/server.ts @@ -0,0 +1,42 @@ +import type { NamedSSRLoadedRendererValue, SSRResult } from 'astro'; + +type RendererContext = { + result: SSRResult; +}; + +async function check( + this: RendererContext, + Component: any, + //props: Record, + //children: any, +) { + + if (typeof Component !== 'function') return false; + + // in a real-world scenario, this would be a more complex function + // that checks if the component should be rendered + return true; +} + +async function renderToStaticMarkup( + this: RendererContext, + Component: any, + props: Record, + //{ default: children, ...slotted }: Record, + //metadata: AstroComponentMetadata | undefined, +) { + // in a real-world scenario, this would be a more complex function + // actually rendering the components return value (which might be an AST/VDOM) + // and render it as an HTML string + const vdom = Component(props); + return { attrs: {}, html: `<${vdom.tag}>${vdom.text} (rendered by server.ts)` }; +} + +const renderer: NamedSSRLoadedRendererValue = { + name: 'custom-renderer', + check, + renderToStaticMarkup, + supportsAstroStaticSlot: false, +}; + +export default renderer; \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-renderer/src/pages/index.astro b/packages/astro/test/fixtures/custom-renderer/src/pages/index.astro new file mode 100644 index 0000000000..f241df2d4b --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/src/pages/index.astro @@ -0,0 +1,30 @@ +--- +import CustomRendererTest from '../components/CustomRendererTest'; +--- + + + + Custom Framework / Custom Renderer + + +

Client Directives

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + diff --git a/packages/astro/test/fixtures/custom-renderer/tsconfig.json b/packages/astro/test/fixtures/custom-renderer/tsconfig.json new file mode 100644 index 0000000000..f1ad59fe06 --- /dev/null +++ b/packages/astro/test/fixtures/custom-renderer/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "astro/tsconfigs/base", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@custom-renderer/*": ["src/custom-renderer/*"] + }, + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3baaf9a02b..8c321c363c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -968,6 +968,12 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + packages/astro/e2e/fixtures/custom-renderer: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/e2e/fixtures/dev-toolbar: dependencies: '@astrojs/preact': @@ -2942,6 +2948,12 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/custom-renderer: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/test/fixtures/data-collections: dependencies: astro: