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

Remove misleading warning when using a custom renderer (#12461)

* fix: this message adds no value to developers; it checks against a static list of renderers while Astro allows to dynamically add custom  renderers

* feat: added framework-custom example to demonstrate the use of custom renderers with the log message fixed

* chore: changeset added and package lock updated

* chore: fix lint issue, but keeping arguments commented out for reference (real-world use)

* chore: removed the example and updated the changeset accordingly

* test: added fixture and test to prove the new behaviour

* test: removing this specific test since it's only guarding if we ever revert this PR

* Update test

---------

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
Co-authored-by: bluwy <bjornlu.dev@gmail.com>
This commit is contained in:
kyr0 2024-12-04 11:29:12 +01:00 committed by GitHub
parent f56d349ccc
commit 62939add0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 218 additions and 9 deletions

View file

@ -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.

View file

@ -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();

View file

@ -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);
});
});
});

View file

@ -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()]
});

View file

@ -0,0 +1,11 @@
{
"name": "@test/custom-renderer",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*"
},
"scripts": {
"dev": "astro dev"
}
}

View file

@ -0,0 +1,10 @@
export interface Props {
msg: string;
}
export default function CustomRendererTest({ msg }: Props) {
return {
tag: "p",
text: msg
}
}

View file

@ -0,0 +1,25 @@
export default (parentElement: HTMLElement) =>
async (
Component: any,
props: Record<string, any>,
//{ default: children, ...slotted }: Record<string, any>,
//{ client }: Record<string, string>,
) => {
// 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 });
};

View file

@ -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());
},
},
};
}

View file

@ -0,0 +1,42 @@
import type { NamedSSRLoadedRendererValue, SSRResult } from 'astro';
type RendererContext = {
result: SSRResult;
};
async function check(
this: RendererContext,
Component: any,
//props: Record<string, any>,
//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<string, any>,
//{ default: children, ...slotted }: Record<string, any>,
//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)</${vdom.tag}>` };
}
const renderer: NamedSSRLoadedRendererValue = {
name: 'custom-renderer',
check,
renderToStaticMarkup,
supportsAstroStaticSlot: false,
};
export default renderer;

View file

@ -0,0 +1,30 @@
---
import CustomRendererTest from '../components/CustomRendererTest';
---
<html>
<head>
<title>Custom Framework / Custom Renderer</title>
</head>
<body>
<h1>Client Directives</h1>
<div>
<CustomRendererTest msg="client:only" client:only="custom-renderer" />
</div>
<div>
<CustomRendererTest msg="client:load" client:load />
</div>
<div>
<CustomRendererTest msg="client:visible" client:visible />
</div>
<div>
<CustomRendererTest msg="client:media" client:media="(max-width: 50em)" />
</div>
<div>
<CustomRendererTest msg="client:idle" client:idle />
</div>
<div>
<CustomRendererTest msg="none (SSR)" />
</div>
</body>
</html>

View file

@ -0,0 +1,9 @@
{
"extends": "astro/tsconfigs/base",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@custom-renderer/*": ["src/custom-renderer/*"]
},
}
}

View file

@ -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: