Static content for jupyterlab extension

This is honestly pretty tough, since as extension developers we have no control over the Webpack config.

Here are a few strategies I’ve used with success:

Pure CSS

Write a CSS file, targeting your .jp-xkcdCartoon, and have it reference the image by URL. Eg,

/* style.css */
.jp-xkcdCartoon {
  backgroundImage: url('./local/path/to/img.png');
}

And in your JS file, import the CSS file:

// main.ts
import "./path/to/style.css"

This works because Webpack will see the “import” in your JS file, and follow it. Then, a separate Webpack plugin (defined in the JupyterLab build config) will in-line the stylesheet and the image. This is the most reliable, but rather inflexible and means you won’t be able to get the source data from JS.

URL loading

Using url-loader is best if you need access to raw data from within JS.

// main.ts
import * as comic from "./path/to/img.png"
// `comic` will be a Base64 string

Note that for some file types, this may not work directly. You can force the use of url-loader with a prefix:

// main.ts
import * as myTemplateFile from "url-loader!./path/to/my/data.html";
// myTemplateFile will be a regular text string

File reference

If none of those work, you can use file-loader to import it. This will make Webpack include it with the build, but won’t give you direct data access (you’ll need to fetch() it yourself). I’ve found this to be the least reliable method, because you need to be very careful constructing URLs (making sure they work on end-user deployments), but it has the benefit of not needing to pass data around directly.

Wrapping it all up

The build system in JupyterLab is very complicated right now, unfortunately. This is by necessity, given the technical constraints imposed by the build-chain (and the web as a whole). You can follow discussion on future direction here: Notes on JupyterLab Build

2 Likes