You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/config.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -161,7 +161,7 @@ Whether to show the previous & next links in the footer; defaults to true. The p
161
161
162
162
## dynamicPaths <ahref="https://github.com/observablehq/framework/releases/tag/v1.11.0"class="observablehq-version-badge"data-version="^1.11.0"title="Added in 1.11.0"></a>
163
163
164
-
The list of [parameterized pages](./params), [dynamic pages](./page-loaders), and [embedded modules](./embeds) to generate, either as a (synchronous) iterable of strings, or a function that returns an async iterable of strings if you wish to load the list of dynamic pages asynchronously.
164
+
The list of [parameterized pages](./params), [dynamic pages](./page-loaders), and [exported modules and files](./embeds) to generate, either as a (synchronous) iterable of strings, or a function that returns an async iterable of strings if you wish to load the list of dynamic pages asynchronously.
In addition to generating full-page apps, Framework can generate modules to embed analytics — such as individual charts or tables, or coordinated interactive views — in external applications. Embedded modules take full advantage of Framework’s polyglot, baked data architecture for instant page loads.
5
+
# Embedding <ahref="https://github.com/observablehq/framework/pull/1637"class="observablehq-version-badge"data-version="prerelease"title="Added in #1637"></a>
4
6
5
-
Embedded modules are vanilla JavaScript, and behave identically when embedded in an external application as on a Framework page. As always, you can load data from a [data loader](./data-loaders) using [`FileAttachment`](./files), and you can [import](./imports)[self-hosted](./imports#self-hosting-of-npm-imports) local modules and libraries from npm; file and import resolutions are baked into the generated code at build time so that imported modules “just work”.
7
+
In addition to standalone apps, you can use Framework to embed interactive views within other applications. Framework supports multiple approaches to embedding:
6
8
7
-
Embedded modules are often written as component functions that return DOM elements. These functions can take options (or “props”), and typically load their own data. For example, below is a simple `chart.js` module that exports a `Chart` function that renders a scatterplot of global surface temperature data.
9
+
-[exported modules](#exported-modules) for seamless integration and performance,
10
+
-[exported files](#exported-files) for hotlinking images, data, and other assets, or
11
+
-[iframe embeds](#iframe-embeds) for compatibility.
12
+
13
+
## Exported modules
14
+
15
+
Framework allows [JavaScript modules](./imports#local-imports) to be exported for use in another application. Exported modules are vanilla JavaScript and behave identically in an external web application as on a Framework page. As with local modules, exported modules can load data from a [static file](./files) or a [data loader](./data-loaders), [import](./imports) other local modules, and import libraries from [npm](./imports#npm-imports) or [JSR](./imports#jsr-imports).
16
+
17
+
Exported modules typically define **data components**: functions that render dynamic content, such as a chart or table, by returning a DOM element. Data components can take options (or “props”), and load any needed data using [`FileAttachment`](./files). For example, the `chart.js` module below exports a `Chart` data component that loads a CSV file and renders a responsive scatterplot of global surface temperature.
When Framework builds your app, any transitive static imports are preloaded automatically when the embedded module is imported. This ensures optimal performance by avoiding long request chains.
29
-
30
-
</div>
36
+
Data components benefit from Framework’s baked data architecture for instant loads. File and import resolutions are baked into exported modules at build time. Libraries from npm are [self-hosted](./imports#self-hosting-of-npm-imports) for stability, security, and performance. And transitive static imports are preloaded to avoid long request chains.
31
37
32
-
## Embedding modules
33
-
34
-
To allow a module to be embedded in an external application, declare the module’s path in your [config file](./config) using the [**dynamicPaths** option](./config#dynamic-paths). For example, to embed a single component named `chart.js`:
38
+
To export a module, declare the module’s path in your [config file](./config) using the [**dynamicPaths** option](./config#dynamic-paths). For example, to export the module named `chart.js`:
35
39
36
40
```js run=false
37
41
exportdefault {
@@ -41,7 +45,7 @@ export default {
41
45
};
42
46
```
43
47
44
-
Or for [parameterized routes](./params), name the component`product-[id]/chart.js`, then load a list of product identifiers from a database with a SQL query:
48
+
Or for [parameterized routes](./params), name the module`product-[id]/chart.js`, then load a list of product identifiers from a database with a SQL query:
45
49
46
50
```js run=false
47
51
importpostgresfrom"postgres";
@@ -57,7 +61,9 @@ export default {
57
61
};
58
62
```
59
63
60
-
An embedded component can be imported into a vanilla web application like so:
64
+
### Importing exported modules
65
+
66
+
An exported module can then be imported into a vanilla web application like so:
The code above assumes the Framework app is called “my-app” and that it’s deployed to Observable Cloud in the workspace named “my-workspace”.
75
-
76
-
</div>
77
-
78
-
<divclass="note">
79
-
80
-
If the external (host) application is on a different origin than the Framework app — for example, if the host application is on example.com and the Framework app is on app.example.com — then you will need to [enable CORS](https://enable-cors.org/) on app.example.com or use a proxy to forward requests from example.com to app.example.com for same-origin serving.
80
+
Observable Cloud support for cross-origin resource sharing (CORS) is not yet generally available and is needed for exported modules. If you are interested in beta-testing this feature, please [email us](mailto:[email protected]). For public apps, you can use a third-party host supporting CORS such as GitHub Pages.
81
81
82
82
</div>
83
83
@@ -103,28 +103,39 @@ export function EmbedChart() {
103
103
104
104
<div class="tip">
105
105
106
-
Since both dynamic import and the imported component are async, the code above is careful to clean up the effect and avoid race conditions.
106
+
Some web tooling such as Vite and Webpack erroneously rewrite external dynamic imports. You may need to include a comment such as `import(/* @vite-ignore */ …)` or `import(/* webpackIgnore: true */ …)` to disable this behavior.
107
107
108
108
</div>
109
109
110
-
<div class="tip">
110
+
## Exported files
111
111
112
-
You can alternatively embed Framework pages using [iframe embeds](https://observablehq.observablehq.cloud/framework-example-responsive-iframe/).
112
+
In addition to modules, you can declare specific files to export using the [**dynamicPaths** config option](./config#dynamic-paths). Exported files are published under a stable URL that can be linked to and loaded from an external application. Exported files can be either [static files](./files) or generated dynamically by [data loaders](./data-loaders), and can use [parameterized routes](./params). For example, to export the file `/robots.txt`:
113
113
114
-
</div>
114
+
```js run=false
115
+
exportdefault {
116
+
dynamicPaths: [
117
+
"/robots.txt"
118
+
]
119
+
};
120
+
```
115
121
116
-
## Developing modules
122
+
## Iframe embeds
117
123
118
-
To develop your component, you can import it into a Framework page like normal, giving you instant reactivity as you make changes to the component or its data.
124
+
You can alternatively embed Framework pages using iframes. Pages that are intended to be embedded via iframe typically disable Framework’s built-in user interface using [Markdown front matter](./markdown#front-matter):
119
125
120
-
```js echo
121
-
import {Chart} from"./chart.js";
126
+
```yaml
127
+
---
128
+
sidebar:false
129
+
header:false
130
+
footer:false
131
+
pager:false
132
+
---
122
133
```
123
134
124
-
To instantiate the imported component, simply call the function:
135
+
For the page `/chart`, you can declare an iframe like so:
A Framework page can serve as live documentation for your component: you can describe and demonstrate all the states and options for your component, and review the behavior visually.
141
+
With a little bit of additional JavaScript, you can also implement [responsive iframe embeds](https://observablehq.observablehq.cloud/framework-example-responsive-iframe/) which resize automatically to fit the content of the page.
0 commit comments