Skip to content

Commit

Permalink
feat: actually helpful route message
Browse files Browse the repository at this point in the history
  • Loading branch information
mxdvl committed Aug 24, 2024
1 parent d553cfa commit 48c3f04
Showing 1 changed file with 57 additions and 34 deletions.
91 changes: 57 additions & 34 deletions src/esbuild_plugins/build_routes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Plugin } from "esbuild";
import type { OutputFile, Plugin } from "esbuild";
import { dirname } from "@std/path/dirname";
import { ensureDir } from "@std/fs/ensure-dir";
import { get_route_html } from "./get_route_html.ts";
Expand All @@ -9,6 +9,48 @@ interface SSROutput {
css?: { code: string };
}

const FAILURE_FLAG = "<!--mononykus:failed-->";

/** safely render Svelte components */
async function render(
{ text }: OutputFile,
): Promise<{ html: string; css: string; head: string }> {
try {
const module = await import(
"data:application/javascript," + encodeURIComponent(text)
) as {
default: {
render(): SSROutput;
};
};

const { html, css: raw_css, head: raw_head } = module.default.render();

const css = raw_css?.code ?? "";

// remove any duplicate module imports (in cases where a page uses an island more than once)
const modules = new Set();
const head = raw_head.replace(
/<script[\s\S]*?<\/script>/g,
(module) => {
if (modules.has(module)) {
return "";
}
modules.add(module);
return module;
},
);

return { html, css, head };
} catch (error) {
return {
html: `${FAILURE_FLAG}<h1>ERROR</h1><pre>${String(error)}</pre>`,
head: "",
css: "",
};
}
}

export const build_routes: Plugin = {
name: "mononykus/build-routes",
setup(build) {
Expand All @@ -17,51 +59,32 @@ export const build_routes: Plugin = {

const routes = result.outputFiles ?? [];

await Promise.allSettled(routes.map(async (route) => {
const module = await import(
"data:application/javascript," + encodeURIComponent(route.text)
) as {
default: {
render(): SSROutput;
};
};

const { html, css: _css, head } = module.default.render();

// remove any duplicate module imports (in cases where a page uses an island more than once)
const modules = new Set();
const deduped_head = head.replace(
/<script[\s\S]*?<\/script>/g,
(module) => {
if (modules.has(module)) {
return "";
}
modules.add(module);
return module;
},
);

const css = _css?.code ?? "";

const results = await Promise.all(routes.map(async (route) => {
const dist_path = route.path.replace(".js", ".html");
await ensureDir(dirname(dist_path));

const template = await render(route);

await Deno.writeTextFile(
dist_path,
await get_route_html({ html, css, head: deduped_head }),
await get_route_html(template),
);
})).then((results) => {
const { length } = results.filter(({ status }) =>
status === "rejected"
);
if (length > 0) console.log(`Failed to build ${length} routes.`);
});

return template.html.startsWith(FAILURE_FLAG) ? dist_path : undefined;
}));

console.log(
`Built ${routes.length} routes in ${
Math.ceil(performance.now() - start)
}ms`,
);

const failures = results.filter((result) => !!result);
if (failures.length > 0) {
console.warn(
["–––", "Failed to build some routes:", ...failures].join("\n"),
);
}
});
},
};

0 comments on commit 48c3f04

Please sign in to comment.