Skip to content

Commit 85e3d7e

Browse files
committed
modulepreload
1 parent 4f094d5 commit 85e3d7e

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

src/render.ts

+22-15
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type RenderInternalOptions =
4646

4747
function render(parseResult: ParseResult, {path, pages, preview, hash}: RenderOptions & RenderInternalOptions): string {
4848
const showSidebar = pages && pages.length > 1;
49+
const imports = getImportMap(parseResult);
4950
return `<!DOCTYPE html>
5051
<meta charset="utf-8">
5152
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
@@ -54,22 +55,9 @@ ${
5455
}<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Source+Serif+Pro:ital,wght@0,400;0,600;0,700;1,400;1,600;1,700&display=swap">
5556
<link rel="stylesheet" type="text/css" href="/_observablehq/style.css">
5657
<script type="importmap">
57-
${JSON.stringify(
58-
{
59-
imports: Object.fromEntries(
60-
parseResult.imports
61-
.map(({name}) => name)
62-
.filter((name) => name.startsWith("npm:"))
63-
.concat(["npm:d3", "npm:htl", "npm:@observablehq/plot", "npm:@observablehq/inputs"]) // recommended libraries
64-
.map((name) => [name, `https://cdn.jsdelivr.net/npm/${name.slice(4)}/+esm`])
65-
.concat([["npm:@observablehq/runtime", "/_observablehq/runtime.js"]])
66-
)
67-
},
68-
null,
69-
2
70-
)}
58+
${JSON.stringify({imports: Object.fromEntries(imports)}, null, 2)}
7159
</script>
72-
<link rel="modulepreload" href="/_observablehq/runtime.js">
60+
${imports.map(([, href]) => `<link rel="modulepreload" href="${href}">`).join("\n")}
7361
<script type="module">
7462
7563
import {${preview ? "open, " : ""}define} from "/_observablehq/client.js";
@@ -116,6 +104,25 @@ ${parseResult.html}</main>
116104
`;
117105
}
118106

107+
function getImportMap(parseResult: ParseResult): [name: string, href: string][] {
108+
const modules = new Set(["npm:@observablehq/runtime"]);
109+
if (parseResult.cells.some((c) => c.inputs?.includes("d3") || c.inputs?.includes("Plot"))) modules.add("npm:d3");
110+
if (parseResult.cells.some((c) => c.inputs?.includes("Plot"))) modules.add("npm:@observablehq/plot");
111+
if (parseResult.cells.some((c) => c.inputs?.includes("htl") || c.inputs?.includes("Inputs"))) modules.add("npm:htl");
112+
if (parseResult.cells.some((c) => c.inputs?.includes("Inputs"))) modules.add("npm:@observablehq/inputs");
113+
for (const {name} of parseResult.imports) {
114+
if (name.startsWith("npm:")) {
115+
modules.add(name);
116+
}
117+
}
118+
return Array.from(modules, (name) => [
119+
name,
120+
name === "npm:@observablehq/runtime"
121+
? "/_observablehq/runtime.js" // self-hosted
122+
: `https://cdn.jsdelivr.net/npm/${name.slice(4)}/+esm`
123+
]);
124+
}
125+
119126
// TODO Adopt Hypertext Literal?
120127
function escapeDoubleQuoted(value): string {
121128
return `${value}`.replace(/["&]/g, entity);

0 commit comments

Comments
 (0)