# Embedded notebook still loading static imports dynamically?

**URL:** <https://talk.observablehq.com/t/embedded-notebook-still-loading-static-imports-dynamically/4389>\
**Category:** Uncategorized\
**Created:** [December 27, 2020, 2:33am UTC](https://talk.observablehq.com/t/embedded-notebook-still-loading-static-imports-dynamically/4389 "2020-12-27T02:33:05Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![yurivish](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/yurivish/32/198_2.png) [@yurivish](https://talk.observablehq.com/u/yurivish)\
**Post date:** [December 27, 2020, 2:33am UTC](https://talk.observablehq.com/t/embedded-notebook-still-loading-static-imports-dynamically/4389/1 "2020-12-27T02:33:05Z")

</div>

I noticed that my new notebook-powered [personal site](https://yuri.is) loads a dependency, [htl](https://observablehq.com/@observablehq/htl), from jsdelivr, despite the code being bundled using `npm`:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/c/ccc5ac38970e353e981c060e4dc57e1b972d23de.png)  
(you can see the full results on [webpagespeedtest.org](https://webpagetest.org/result/201227_DiDM_943a74b91fc4ad8986a3ee26664a5ebf/1/details/#waterfall_view_step1))

I thought that treating notebooks as npm modules (as described in [advanced embedding](https://observablehq.com/@observablehq/downloading-and-embedding-notebooks)) would let me self-host a notebook and its dependencies without depending on outside infrastructure.

It might be that I’m doing something incorrectly, or have a misapprehension about the nature of bundling code for deployment outside of [observablehq.com](http://observablehq.com). If there is a way to bundle together a notebook and its dependencies I’d be very curious to know how to do it.

Many thanks!

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [December 27, 2020, 3:14am UTC](https://talk.observablehq.com/t/embedded-notebook-still-loading-static-imports-dynamically/4389/2 "2020-12-27T03:14:32Z")

</div>

This dependency comes from the imported notebook:

> **[Hypertext Literal](https://observablehq.com/@observablehq/htl)**
>
> Inspired by lit-html and HTM, and referencing the fantastically precise HTML5 spec, we built hypertext literal: a tagged template literal for HTML which interpolates values based on context, allowing automatic escaping and the interpolation of...

Which requires `htl` from npm:

```auto
htl = require("htl@0.2")

```

This is not a static import — it’s a dynamic require, and as such, it isn’t treated specially when you download a notebook for embedded. The inclusion of transitive dependencies in the downloaded tarball only applies to _notebook_ imports, not to require (and dynamic ES imports).

That said, you can remove this external dependency, too, by specifying a custom require resolver when you embed your notebook, and then pointing `htl` at a local copy rather than loading it from jsDelivr. That technique is described here:

> **[observablehq/notebook-download-example](https://github.com/observablehq/notebook-download-example)**
>
> An example of downloading and embedding an Observable notebook into a web app.

And it would look something like this:

```auto
// Initialize the Observable Runtime, telling it to use our local copy of htl
// rather than loading one from a CDN.
const runtime = new Runtime(new Library(name => {
  switch (name) {
    case "htl@0.2": return htl;
  }
}));

```

---

<div class="post-metadata">

**Author:** ![yurivish](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/yurivish/32/198_2.png) [@yurivish](https://talk.observablehq.com/u/yurivish)\
**Post date:** [December 27, 2020, 4:32am UTC](https://talk.observablehq.com/t/embedded-notebook-still-loading-static-imports-dynamically/4389/3 "2020-12-27T04:32:45Z")

</div>

Thank you for the great explanation. That makes a lot of sense – I hadn’t realized that the dynamic call was for a dynamic import.

Happy holidays! 🎄
