Add hydration to Solid renderer (#1479)
* feat: add hydration to Solid renderer * fix: intersection observer, move script to the end
This commit is contained in:
parent
9874645d8b
commit
f8d1a35ace
4 changed files with 17 additions and 22 deletions
|
@ -1,16 +1,11 @@
|
|||
import { createComponent } from 'solid-js';
|
||||
import { render } from 'solid-js/web';
|
||||
import { hydrate, createComponent } from 'solid-js/web';
|
||||
|
||||
export default (element) => (Component, props, childHTML) => {
|
||||
// Solid's `render` does not replace the element's children.
|
||||
// Deleting the root's children is necessary before calling `render`.
|
||||
element.replaceChildren();
|
||||
|
||||
const children = document.createElement('astro-fragment');
|
||||
children.innerHTML = childHTML;
|
||||
|
||||
// Using Solid's `render` method ensures that a `root` is created
|
||||
// Using Solid's `hydrate` method ensures that a `root` is created
|
||||
// in order to properly handle reactivity. It also handles
|
||||
// components that are not native HTML elements.
|
||||
render(() => createComponent(Component, { ...props, children }), element);
|
||||
hydrate(() => createComponent(Component, { ...props, children }), element);
|
||||
};
|
||||
|
|
|
@ -2,17 +2,18 @@ export default {
|
|||
name: '@astrojs/renderer-solid',
|
||||
client: './client',
|
||||
server: './server',
|
||||
knownEntrypoints: ['solid-js', 'solid-js/web'],
|
||||
external: ['solid-js/web/dist/server.js', 'solid-js/dist/server.js', 'babel-preset-solid'],
|
||||
knownEntrypoints: ['solid-js', 'solid-js/web', 'solid-js/store'],
|
||||
external: ['solid-js/web/dist/server.js', 'solid-js/store/dist/server.js', 'solid-js/dist/server.js', 'babel-preset-solid'],
|
||||
jsxImportSource: 'solid-js',
|
||||
jsxTransformOptions: async ({ isSSR }) => {
|
||||
const [{ default: solid }] = await Promise.all([import('babel-preset-solid')]);
|
||||
const options = {
|
||||
presets: [solid({}, { generate: isSSR ? 'ssr' : 'dom' })],
|
||||
presets: [solid({}, { generate: isSSR ? 'ssr' : 'dom', hydratable: true })],
|
||||
};
|
||||
|
||||
if (isSSR) {
|
||||
options.alias = {
|
||||
'solid-js/store': 'solid-js/store/dist/server.js',
|
||||
'solid-js/web': 'solid-js/web/dist/server.js',
|
||||
'solid-js': 'solid-js/dist/server.js',
|
||||
};
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
import { createComponent } from 'solid-js';
|
||||
import { renderToStringAsync, ssr } from 'solid-js/web/dist/server.js';
|
||||
import { renderToString, ssr, createComponent } from 'solid-js/web/dist/server.js';
|
||||
|
||||
async function check(Component, props, children) {
|
||||
function check(Component, props, children) {
|
||||
if (typeof Component !== 'function') return false;
|
||||
|
||||
const { html } = await renderToStaticMarkup(Component, props, children);
|
||||
const { html } = renderToStaticMarkup(Component, props, children);
|
||||
return typeof html === 'string';
|
||||
}
|
||||
|
||||
async function renderToStaticMarkup(Component, props, children) {
|
||||
const html = await renderToStringAsync(
|
||||
() => () =>
|
||||
function renderToStaticMarkup(Component, props, children) {
|
||||
const html = renderToString(
|
||||
() =>
|
||||
createComponent(Component, {
|
||||
...props,
|
||||
// In Solid SSR mode, `ssr` creates the expected structure for `children`.
|
||||
// In Solid client mode, `ssr` is just a stub.
|
||||
children: ssr([`<astro-fragment>${children}</astro-fragment>`]),
|
||||
children: ssr(`<astro-fragment>${children}</astro-fragment>`),
|
||||
})
|
||||
);
|
||||
return { html };
|
||||
return { html: html + `<script>window._$HYDRATION||(window._$HYDRATION={events:[],completed:new WeakSet})</script>` };
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createComponent } from 'solid-js';
|
||||
import { ssr } from 'solid-js/web/dist/server.js';
|
||||
|
||||
/**
|
||||
* Astro passes `children` as a string of HTML, so we need
|
||||
|
@ -6,7 +6,7 @@ import { createComponent } from 'solid-js';
|
|||
*/
|
||||
const StaticHtml = ({ innerHTML }) => {
|
||||
if (!innerHTML) return null;
|
||||
return () => createComponent('astro-fragment', { innerHTML });
|
||||
return ssr(`<astro-fragment>${innerHTML }</astro-fragment>`);
|
||||
};
|
||||
|
||||
export default StaticHtml;
|
||||
|
|
Loading…
Reference in a new issue