I’ve been running into an issue where
require'd modules intermittently throw a mysterious
Pe: invalid module error if I’ve imported Observable’s runtime library and embedded a notebook in another cell. The following notebook is my attempt to give a minimal example:
The two cells of interest are:
vega-lite (can be replaced with any other module of your choice, in my original case it was
loaded, which embeds an almost-blank notebook using
required Observable runtime and inspector libraries.
In my browser (Chrome, macOS), about ~2/3 of the time
loaded shows an error “
RuntimeError: md could not be resolved”. The other ~1/3 of the time the
req cell fails with
Pe: invalid module.
If I comment out
loaded never seems to get an error. If I comment out
req always seems to be fine. If I comment out the dependencies in
req to change the evaluation order then I can sometimes get no error in either of the cells.
(I also see this in Firefox when I use a polyfill for dynamic import, but I stripped that out to make the example simpler.)
Ultimately I’d like to be able to
require and embed notebooks without fear. I’d appreciate any pointers or advice on how to debug this sort of thing.
After some digging, I think the issue may be that both the imported
observable.Library and the “usual” stdlib instance (that is, the one provided by the Observable runtime in the editor) are adding
define to the global namespace (from their respective copies of
d3-require) and these are overriding each other (?).
One possibly (ugly) solution might be to use the copy of
require given by
@observablehq/runtime whenever possible:
More explicitly, the idea is that the notebook should first import the runtime using the built-in require, and then import all other libraries using a “new” require coming from a Library instance.
edit: One remaining issue is that the
hljs instance (for syntax highlighting in markdown) provided by an imported runtime can still conflict with the “usual” one. I’ve updated the example notebook in this post to illustrate this. After refreshing a bunch of times, I see that sometimes the code in the markdown is properly highlighted, but sometimes not (and then
Uncaught (in promise) Pe: invalid module errors appear in the console).
I’m still curious if there are better ways to deal with all this, but I think I’ve figured out enough to be able to work around these problems. Anyways, I guess the bottom line is that one has to be very careful with imports (such as
@observablehq/runtime) that attach stuff to
Yep, this is what I was going to mention:
You can’t use more than one copy of d3-require (which is used by Observable’s standard library), because they will compete to set the
define global. (And
define has to be a global according to the design of AMD.)
It would be possible to change d3-require to wrap an existing
define global, if present, rather than overwriting it. Though I worry that might cause different problems.
I’m curious why you’re using the Observable runtime to load a notebook within another notebook, rather than using Observable’s native imports? Mind giving a little more detail on what you are trying to accomplish?
Here’s a clean way to embed an Observable notebook within another Observable notebook using an iframe:
Thanks! The iframe approach looks like it might be the best option, all things considered.
Sure! It’s kind of open-ended. I’ve been trying to better understand “how Observable works”, and so I’ve been messing around with the runtime / inspector / parser libraries using Observable itself, since I find the live environment pleasant to work and think in.
For example, I’ve been hacking on a crude re-implementation of how Observable transforms the raw source of notebooks to importable notebook runtime modules, and it’s been helpful to display / check the results in the same notebook:
(This is where I noticed a
d3-fetch import failing).