-
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.
- Loading branch information
Showing
8 changed files
with
118 additions
and
87 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
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<script> | ||
import GreenThenPink from '../../components/GreenThenPink.island.svelte' | ||
</script> | ||
|
||
<GreenThenPink /> |
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,9 +1,12 @@ | ||
<script> | ||
import RedThenBlue from '../components/RedThenBlue.island.svelte' | ||
import GreenThenPink from '../components/GreenThenPink.island.svelte' | ||
import SubDir from '../components/sub_dir/SubDir.island.svelte' | ||
</script> | ||
|
||
Example of nested islands. | ||
|
||
<RedThenBlue /> | ||
<GreenThenPink /> | ||
<GreenThenPink /> | ||
<SubDir /> |
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,7 +1,7 @@ | ||
import * as esbuild from "https://deno.land/x/[email protected]/mod.js"; | ||
import { svelte_components } from "./esbuild_plugins/svelte_components.ts"; | ||
import { svelte_internal } from "./esbuild_plugins/svelte_internal.ts"; | ||
import { build_routes } from "./esbuild_plugins/routes.ts"; | ||
import { build_routes } from "./esbuild_plugins/build_routes.ts"; | ||
import { ensureDir } from "https://deno.land/[email protected]/fs/ensure_dir.ts"; | ||
import { parse } from "https://deno.land/[email protected]/flags/mod.ts"; | ||
import { serve } from "https://deno.land/[email protected]/http/server.ts"; | ||
|
@@ -61,9 +61,9 @@ const routesESBuildConfig: esbuild.BuildOptions = { | |
entryPoints: await get_svelte_files({ dir: "routes/" }), | ||
write: false, | ||
plugins: [ | ||
svelte_components, | ||
svelte_components(site_dir, base_path), | ||
svelte_internal, | ||
build_routes({ base_path }), | ||
build_routes, | ||
], | ||
outdir: build_dir, | ||
...baseESBuildConfig, | ||
|
@@ -73,7 +73,7 @@ const islandsESBuildConfig: esbuild.BuildOptions = { | |
entryPoints: await get_svelte_files({ dir: "components/" }), | ||
write: true, | ||
plugins: [ | ||
svelte_components, | ||
svelte_components(site_dir, base_path), | ||
svelte_internal, | ||
], | ||
outdir: build_dir + "components/", | ||
|
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,19 @@ | ||
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; | ||
hydrator: string; | ||
} | ||
const template = ({ css, head, html, hydrator }: TemplateOptions) => ` | ||
|
||
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 +22,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,27 +4,42 @@ 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"; | ||
import type { ComponentType } from "npm:svelte"; | ||
|
||
const filter = /\.svelte$/; | ||
const name = "mononykus/svelte"; | ||
|
||
/** force wrapping the actual component in a synthetic one */ | ||
const one_claw_synthetic = "?one-claw-synthetic"; | ||
const ssr_island = "?ssr_island"; | ||
|
||
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"; | ||
|
@@ -50,7 +65,7 @@ export const svelte_components: Plugin = { | |
) { | ||
return { | ||
path: resolve(dirname(importer), path), | ||
suffix: one_claw_synthetic, | ||
suffix: ssr_island, | ||
}; | ||
} | ||
} | ||
|
@@ -61,8 +76,14 @@ export const svelte_components: Plugin = { | |
.replace(/(\.island)?\.svelte$/, "") | ||
.replaceAll(/(\.|\W)/g, "_"); | ||
|
||
const source = suffix === one_claw_synthetic | ||
? OneClaw({ path, name }) | ||
const module_src = normalize("/" + base_path + path.split(site_dir)[1]) | ||
.replace( | ||
/svelte$/, | ||
"js", | ||
); | ||
|
||
const source = suffix === ssr_island | ||
? OneClaw({ path, name, module_src }) | ||
: await Deno.readTextFile(path); | ||
|
||
const { js: { code } } = compile(source, { | ||
|
@@ -74,7 +95,41 @@ export const svelte_components: Plugin = { | |
filename: basename(path), | ||
}); | ||
|
||
if (generate === "dom" && path.endsWith(".island.svelte")) { | ||
const hydrator = (name: string, Component: ComponentType) => { | ||
try { | ||
document.querySelectorAll( | ||
`one-claw[name='${name}']:not(one-claw one-claw)`, | ||
).forEach((target) => { | ||
const load = performance.now(); | ||
console.groupCollapsed( | ||
`Hydrating %c${name}%c`, | ||
"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};(${hydrator.toString()})("${name}", ${name}_island)`, | ||
}); | ||
} | ||
|
||
return ({ contents: code }); | ||
}); | ||
}, | ||
}; | ||
}); |