-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
inject module loading into the head (WIP)
it’s broken somehow following a refactor in main, will look later
- Loading branch information
Showing
3 changed files
with
98 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,47 @@ | ||
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(_); | ||
} | ||
}; | ||
// import type { SvelteComponent } from "https://esm.sh/v115/[email protected]/types/runtime/index.d.ts"; | ||
|
||
interface TemplateOptions { | ||
css: string; | ||
head: string; | ||
html: string; | ||
hydrator: string; | ||
} | ||
const template = ({ css, head, html, hydrator }: TemplateOptions) => ` | ||
|
||
// // this function is stringified inline in the page | ||
// // putting it here gives us type safety etc | ||
// export const hydrate_island = (component: SvelteComponent, name: string) => { | ||
// try { | ||
// document.querySelectorAll( | ||
// `one-claw[name='${name}']:not(one-claw one-claw)`, | ||
// ).forEach((target, i) => { | ||
// const load = performance.now(); | ||
// console.group( | ||
// `Hydrating %c${name}%c (instance #${(i + 1)})`, | ||
// "color: orange", | ||
// "color: reset", | ||
// ); | ||
// console.log(target); | ||
// const props = JSON.parse(target.getAttribute("props") ?? "{}"); | ||
// new component({ target, props, hydrate: true }); | ||
// console.log( | ||
// `Done in %c${Math.round((performance.now() - load) * 1000) / 1000}ms`, | ||
// "color: orange", | ||
// ); | ||
// console.groupEnd(); | ||
// }); | ||
// } catch (_) { | ||
// console.error(_); | ||
// } | ||
// }; | ||
|
||
const template = ({ css, head, html }: 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">${hydrator}</script> | ||
<style>${css}</style> | ||
</head> | ||
<body> | ||
|
@@ -61,23 +50,15 @@ const template = ({ css, head, html, hydrator }: TemplateOptions) => ` | |
</html> | ||
`; | ||
|
||
const island_hydrator = (base = "") => ` | ||
const component_path = "${base}"; | ||
const hydrate_island = ${hydrate_island.toString()}; | ||
document.querySelectorAll("one-claw[name]:not(one-claw one-claw)").forEach(hydrate_island); | ||
`; | ||
|
||
export const get_route_html = ({ html, css, head, base_path }: { | ||
export const get_route_html = ({ html, css, head }: { | ||
html: string; | ||
css: string; | ||
head: string; | ||
base_path?: string; | ||
}) => { | ||
const page = template({ | ||
css, | ||
head, | ||
html, | ||
hydrator: island_hydrator(normalize(`/${base_path}/components/`)), | ||
}); | ||
|
||
try { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import { | |
resolve, | ||
} from "https://deno.land/[email protected]/path/mod.ts"; | ||
import type { Plugin } from "https://deno.land/x/[email protected]/mod.js"; | ||
import { normalize } from "https://deno.land/[email protected]/path/mod.ts"; | ||
import { compile } from "npm:svelte/compiler"; | ||
|
||
const filter = /\.svelte$/; | ||
|
@@ -12,19 +13,32 @@ const name = "mononykus/svelte"; | |
/** force wrapping the actual component in a synthetic one */ | ||
const one_claw_synthetic = "?one-claw-synthetic"; | ||
|
||
const OneClaw = ({ path, name }: { path: string; name: string }) => | ||
const OneClaw = ( | ||
{ path, name, module_src }: { | ||
path: string; | ||
name: string; | ||
module_src: string; | ||
}, | ||
) => | ||
`<!-- synthetic component --> | ||
<script> | ||
import Island from "${path}"; | ||
</script> | ||
<one-claw props={JSON.stringify($$props)} name="${name}"> | ||
<Island {...$$props} /> | ||
</one-claw> | ||
<style> | ||
one-claw { display: contents } | ||
</style>`; | ||
<script> | ||
import Island from "${path}"; | ||
</script> | ||
<svelte:head> | ||
<script type="module" src="${module_src}"></script> | ||
</svelte:head> | ||
<one-claw props={JSON.stringify($$props)} name="${name}"> | ||
<Island {...$$props} /> | ||
</one-claw> | ||
<style> | ||
one-claw { display: contents } | ||
</style> | ||
`; | ||
|
||
export const svelte_components: Plugin = { | ||
export const svelte_components = ( | ||
site_dir: string, | ||
base_path: string, | ||
): Plugin => ({ | ||
name, | ||
setup(build) { | ||
const generate = build.initialOptions.write ? "dom" : "ssr"; | ||
|
@@ -61,8 +75,14 @@ export const svelte_components: Plugin = { | |
.replace(/(\.island)?\.svelte$/, "") | ||
.replaceAll(/(\.|\W)/g, "_"); | ||
|
||
const module_src = normalize("/" + base_path + path.split(site_dir)[1]) | ||
.replace( | ||
/svelte$/, | ||
"js", | ||
); | ||
|
||
const source = suffix === one_claw_synthetic | ||
? OneClaw({ path, name }) | ||
? OneClaw({ path, name, module_src }) | ||
: await Deno.readTextFile(path); | ||
|
||
const { js: { code } } = compile(source, { | ||
|
@@ -74,7 +94,38 @@ export const svelte_components: Plugin = { | |
filename: basename(path), | ||
}); | ||
|
||
if (suffix === one_claw_synthetic) { | ||
const x = () => { | ||
try { | ||
document.querySelectorAll( | ||
`one-claw[name='${name}']:not(one-claw one-claw)`, | ||
).forEach((target, i) => { | ||
const load = performance.now(); | ||
console.group( | ||
`Hydrating %c${name}%c (instance #${(i + 1)})`, | ||
"color: orange", | ||
"color: reset", | ||
); | ||
console.log(target); | ||
const props = JSON.parse(target.getAttribute("props") ?? "{}"); | ||
// new component({ target, props, hydrate: true }); | ||
console.log( | ||
`Done in %c${ | ||
Math.round((performance.now() - load) * 1000) / 1000 | ||
}ms`, | ||
"color: orange", | ||
); | ||
console.groupEnd(); | ||
}); | ||
} catch (_) { | ||
console.error(_); | ||
} | ||
}; | ||
|
||
return ({ contents: code + x.toString() }); | ||
} | ||
|
||
return ({ contents: code }); | ||
}); | ||
}, | ||
}; | ||
}); |