Yell is optimized for SSR. Render your YAML to HTML on the server, ship the HTML to the client, and hydrate only the interactive islands.
import { parseYAML, renderToString, createRegistry, registerComponent } from '@yell/core';
const registry = createRegistry();
registerComponent(registry, 'Button', { component: ButtonComponent });
const yaml = `
app:
children:
- type: Button
props:
label: "Submit"
`;
const config = parseYAML(yaml);
const { html, hydrationMap } = renderToString(config, registry);
// Send html to client
// Store hydrationMap for client hydration
For large pages, use streaming to send HTML progressively:
import { createStreamingRenderer } from '@yell/core';
const renderer = createStreamingRenderer(registry);
const stream = renderer.renderToStream(config);
// Write to response incrementally
for await (const chunk of stream) {
response.write(chunk);
}
The hydrationMap returned by renderToString tells the client which nodes need hydration:
const { html, hydrationMap } = renderToString(config, registry);
// hydrationMap looks like:
// {
// "yell-0": { type: "Button", events: ["onClick"] },
// "yell-1": { type: "Modal", events: ["showWhen"] }
// }
import express from 'express';
import { parseYAML, renderToString } from '@yell/core';
import { registry } from './registry';
const app = express();
app.get('/page', (req, res) => {
const config = parseYAML(req.body.yaml);
const { html, hydrationMap } = renderToString(config, registry);
res.send(`
<!DOCTYPE html>
<html>
<body>
${html}
<script>
window.__HYDRATION_MAP__ = ${JSON.stringify(hydrationMap)};
</script>
</body>
</html>
`);
});
import { parseYAML, renderToString } from '@yell/core';
import { registry } from '@/registry';
export default async function Page({ params }) {
const config = parseYAML(params.yaml);
const { html, hydrationMap } = renderToString(config, registry);
return (
<div
dangerouslySetInnerHTML=
data-hydration-map={JSON.stringify(hydrationMap)}
/>
);
}