* feat: add hydration to Solid renderer * fix: intersection observer, move script to the end Co-authored-by: Ryan Carniato <ryansolid@gmail.com>
This commit is contained in:
parent
584947e862
commit
876569d97a
4 changed files with 15 additions and 20 deletions
|
@ -1,16 +1,11 @@
|
||||||
import { createComponent } from 'solid-js';
|
import { hydrate, createComponent } from 'solid-js/web';
|
||||||
import { render } from 'solid-js/web';
|
|
||||||
|
|
||||||
export default (element) => (Component, props, childHTML) => {
|
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');
|
const children = document.createElement('astro-fragment');
|
||||||
children.innerHTML = childHTML;
|
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
|
// in order to properly handle reactivity. It also handles
|
||||||
// components that are not native HTML elements.
|
// components that are not native HTML elements.
|
||||||
render(() => createComponent(Component, { ...props, children }), element);
|
hydrate(() => createComponent(Component, { ...props, children }), element);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ export default {
|
||||||
client: './client',
|
client: './client',
|
||||||
server: './server',
|
server: './server',
|
||||||
knownEntrypoints: ['solid-js', 'solid-js/web', 'solid-js/store', 'solid-js/html', 'solid-js/h'],
|
knownEntrypoints: ['solid-js', 'solid-js/web', 'solid-js/store', 'solid-js/html', 'solid-js/h'],
|
||||||
external: ['solid-js/web/dist/server.cjs', 'solid-js/dist/server.cjs', 'babel-preset-solid'],
|
external: ['solid-js/web/dist/server.cjs', 'solid-js/store/dist/server.cjs', 'solid-js/dist/server.cjs', 'babel-preset-solid'],
|
||||||
jsxImportSource: 'solid-js',
|
jsxImportSource: 'solid-js',
|
||||||
jsxTransformOptions: async ({ isSSR }) => {
|
jsxTransformOptions: async ({ isSSR }) => {
|
||||||
const [{ default: solid }] = await Promise.all([import('babel-preset-solid')]);
|
const [{ default: solid }] = await Promise.all([import('babel-preset-solid')]);
|
||||||
|
@ -18,6 +18,7 @@ export default {
|
||||||
{
|
{
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
alias: {
|
alias: {
|
||||||
|
'solid-js/store': 'solid-js/store/dist/server.cjs',
|
||||||
'solid-js/web': 'solid-js/web/dist/server.cjs',
|
'solid-js/web': 'solid-js/web/dist/server.cjs',
|
||||||
'solid-js': 'solid-js/dist/server.cjs',
|
'solid-js': 'solid-js/dist/server.cjs',
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import { createComponent } from 'solid-js';
|
import { renderToString, ssr, createComponent } from 'solid-js/web/dist/server.cjs';
|
||||||
import { renderToStringAsync, ssr } from 'solid-js/web/dist/server.cjs';
|
|
||||||
|
|
||||||
async function check(Component, props, children) {
|
function check(Component, props, children) {
|
||||||
if (typeof Component !== 'function') return false;
|
if (typeof Component !== 'function') return false;
|
||||||
|
|
||||||
const { html } = await renderToStaticMarkup(Component, props, children);
|
const { html } = renderToStaticMarkup(Component, props, children);
|
||||||
return typeof html === 'string';
|
return typeof html === 'string';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderToStaticMarkup(Component, props, children) {
|
function renderToStaticMarkup(Component, props, children) {
|
||||||
const html = await renderToStringAsync(
|
const html = renderToString(
|
||||||
() => () =>
|
() =>
|
||||||
createComponent(Component, {
|
createComponent(Component, {
|
||||||
...props,
|
...props,
|
||||||
// In Solid SSR mode, `ssr` creates the expected structure for `children`.
|
// In Solid SSR mode, `ssr` creates the expected structure for `children`.
|
||||||
// In Solid client mode, `ssr` is just a stub.
|
// 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 {
|
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
|
* Astro passes `children` as a string of HTML, so we need
|
||||||
|
@ -6,7 +6,7 @@ import { createComponent } from 'solid-js';
|
||||||
*/
|
*/
|
||||||
const StaticHtml = ({ innerHTML }) => {
|
const StaticHtml = ({ innerHTML }) => {
|
||||||
if (!innerHTML) return null;
|
if (!innerHTML) return null;
|
||||||
return () => createComponent('astro-fragment', { innerHTML });
|
return ssr(`<astro-fragment>${innerHTML }</astro-fragment>`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default StaticHtml;
|
export default StaticHtml;
|
||||||
|
|
Loading…
Reference in a new issue