Skip to content

Commit

Permalink
Move the hydration code to a file (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
sndrs authored Apr 21, 2023
2 parents d412277 + 10af406 commit 5c2fe05
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 28 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"editor.defaultFormatter": "denoland.vscode-deno"
},
"cSpell.words": [
"hydrator",
"mononykus"
]
}
79 changes: 51 additions & 28 deletions src/esbuild_plugins/build_routes/get_route_html.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,58 @@
import { normalize } from "https://deno.land/[email protected]/path/mod.ts";
import { format } from "npm:prettier";

// dummy value to put the var name in scope
const component_path = "";

// this function is stringified inline in the page
// putting it here gives us type safety etc
export const hydrate_island = async (target: Element) => {
try {
const name = target.getAttribute("name");
const props = JSON.parse(target.getAttribute("props") ?? "{}");
const load = performance.now();

const Component =
(await import(component_path + name + ".island.js")).default;
console.group(name);
console.info(
`Loaded in %c${Math.round((performance.now() - load) * 1000) / 1000}ms`,
"color: orange",
);

const hydrate = performance.now();
new Component({ target, props, hydrate: true });
target.setAttribute("foraged", "");

console.info(
`Hydrated in %c${
Math.round((performance.now() - hydrate) * 1000) / 1000
}ms%c with`,
"color: orange",
"color: reset",
props,
);
console.groupEnd();
} catch (_) {
console.error(_);
}
};

interface TemplateOptions {
css: string;
head: string;
html: string;
hydrate: string;
hydrator: string;
}
const template = ({ css, head, html, hydrate }: TemplateOptions) => `
const template = ({ css, head, html, hydrator }: TemplateOptions) => `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
${head}
<script type="module">${hydrate}</script>
<script type="module">${hydrator}</script>
<style>${css}</style>
</head>
<body>
Expand All @@ -24,38 +61,24 @@ const template = ({ css, head, html, hydrate }: TemplateOptions) => `
</html>
`;

const islands = (base = "") => `
const hydrate = async (target) => {
try {
const name = target.getAttribute("name");
const props = JSON.parse(target.getAttribute("props") ?? "{}");
const load = performance.now();
const Component = (await import('${
normalize(`/${base}/components/`)
}' + name + '.island.js')).default;
console.group(name);
console.info(\`Loaded in %c\${Math.round((performance.now() - load) * 1000) / 1000}ms\`, "color: orange");
const hydrate = performance.now();
new Component({ target, props, hydrate: true });
target.setAttribute("foraged", "");
console.info(\`Hydrated in %c\${Math.round((performance.now() - hydrate) * 1000) / 1000}ms%c with\`, "color: orange", "color: reset", props);
console.groupEnd();
} catch (_) {
console.error(_)
}
};
document.querySelectorAll("one-claw[name]").forEach(hydrate);`;
const island_hydrator = (base = "") => `
const component_path = "${base}";
const hydrate_island = ${hydrate_island.toString()};
document.querySelectorAll("one-claw[name]").forEach(hydrate_island);
`;

export const get_route_html = ({ html, css, head, base_path }: {
html: string;
css: string;
head: string;
base_path?: string;
}) => {
const page = template({ css, head, html, hydrate: islands(base_path) });
const page = template({
css,
head,
html,
hydrator: island_hydrator(normalize(`/${base_path}/components/`)),
});

try {
return format(
Expand Down

0 comments on commit 5c2fe05

Please sign in to comment.