Closed mbostock closed 4 days ago
@mbostock, this would be a powerful addition and honestly it should be the default for framework in that a observable framework project would work really great if in the barest example it acted as es package module in a monorepo, exporting its pages like components. and that the static site generator was then the layer on top of it that . love the product but i view it as the analytical engine that could go really well in react webapp, potentially expo, refine, storybook and module federation under webpack/rspack.
Current sketch is that you could have a component like this in src/chart.js
:
import * as Plot from "npm:@observablehq/plot";
import {FileAttachment} from "npm:@observablehq/stdlib";
export async function MyChart({color} = {}) {
const gistemp = await FileAttachment("gistemp.csv").csv({typed: true});
return Plot.plot({marks: [Plot.dot(gistemp, {x: "Date", y: "Anomaly", stroke: color})]});
}
To develop this in Framework (in a similar vein to Storybook), you’d do something like src/chart.md
:
```js
import {MyChart} from "./chart.js";
${await MyChart()}
To use this component in another web application, along with its baked data typically generated by a data loader, you’d first (somehow) declare that you want it to be embeddable, resulting in a wrapper script like this generated during build in `dist/chart.js` (or maybe `dist/_embed/chart.js`, TBD):
```js
import {registerFile} from "./_observablehq/stdlib.6bf0b933.js";
import "./_npm/@observablehq/plot@0.6.16/e828d8c8.js"; // module preload
registerFile(new URL("./gistemp.csv", import.meta.url).href, {"name":"./gistemp.csv","mimeType":"text/csv","path":new URL("../_file/gistemp.08e51068.csv", import.meta.url).href,"lastModified":1713890568661});
export * from "./_import/chart.b97f5c97.js";
And like normal, the compiled version of the component in dist/_import/chart.b97f5c97.js
:
import * as Plot from "../_npm/@observablehq/plot@0.6.16/e828d8c8.js";
import {FileAttachment} from "../_observablehq/stdlib.6bf0b933.js";
export async function MyChart({color} = {}) {
const gistemp = await FileAttachment("../gistemp.csv", import.meta.url).csv({typed: true});
return Plot.plot({marks: [Plot.dot(gistemp, {x: "Date", y: "Anomaly", stroke: color})]});
}
Then, in your vanilla web app, you can do something like:
<script type="module">
import {MyChart} from "https://example.observablehq.cloud/app/chart.js";
document.body.append(await MyChart({color: "red"}));
</script>
Notably, I’m not thinking of pages (or chunks of content within pages) as being embeddable, but instead focusing on embedding of JavaScript components.
if the project compiles to the dist one of things that could be done is package exports. drop a package.json in the dist https://nodejs.org/api/packages.html#package-entry-points with the exports object built out with all of the sub paths.
We currently offer only a command-line interface for previewing, building, and deploying projects. We could offer a JavaScript API that provides more flexibility to transpile Markdown and JavaScript.