Require
NotebooksObservable’s require
lets you use thousands of open-source JavaScript modules in your notebooks. If you can think of a task—say date manipulation, math, or music—there’s probably already a module that can help. Just as you can reuse code from other notebooks using imports, you can load JavaScript modules using require
.
Here’s an example requiring Simple Statistics, a module that includes many statistical functions, to compute a standard deviation.
How to use require
The argument to the require
function can be any of the following:
A module name and a version
The most common case specifies a name, an at sign (@), and a version. You can use a semantic version specifier for a range of versions, as below for releases 2.x.x of the moment date and time library.
A module name
If you don’t mind your notebook potentially breaking when a new version of the library is released, omit the version to get the latest version:
A module name, a version, and a path
Sometimes you want to include an individual file from a module, rather than its main exported interface. This is less common, but can be useful for modules that have add-ons or that don’t declare which file to expose as the default. Instead of relying on auto-detection, you can specify the file directly. For example, here’s how we can load D3.js version 6:
A URL
You can also specify a full URL to require
. This lets you point require
at any server, even localhost. For example, we can load ganja.js from jsDelivr.
This technique can even be used to require
a local JavaScript file, though you’ll have to choose the file each time you open the notebook.
Multiple inputs
Specifying multiple inputs—multiple module names, or URLs, or module names with a path—will load all of the named things and combine their exports into one object. This is especially useful for libraries that are designed to work together, such as D3’s constituent modules.
Require’s return value
require
returns a promise with the module’s contents, or, if the module can’t be loaded, a promise rejection.
Most of the time, you’ll use require
in a cell of its own, as in the examples above, so you won’t need to worry about the return value being asynchronous. But if you do want to use require
in the context of other code, you’ll need to await the value of the promise it returns. (Observable implicitly awaits promises across cell boundaries. For more information, see Observable JavaScript.)
Example promise rejection
In some cases, require
won’t find a module or won’t be able to load it, and will return a promise rejection.
Require’s behavior
By default, require uses modules published on npm, a service that hosts over 1 million different modules* created by thousands of individual developers. Because notebooks run in a web environment, we use another service, jsDelivr, that takes npm’s modules and makes them accessible to browsers.
For example, if we call require
with the argument "d3@7"
, it resolves to "${await require.resolve("d3@7")}"
, which is the full URL for the D3 visualization library. You can see the resolved URL by calling require.resolve.
If you see a require
statement in a notebook, searching for its name on npm is likely to pull up its details. Here’s the d3 package on npm, which links to its GitHub information and other documentation.
Note
If you’re using require
with a URL, be sure to follow these requirements for the URL and server:
- Use
https
URLs only, nothttp
. - Use a file with a correct Content-Type header to be used as JavaScript. For example,
raw.githubusercontent.com
serves JavaScript files astext/plain
, which your browser cannot execute as JavaScript - which is why we often usejsDelivr
instead.
Requirements for require
The require
function works with modules that include AMD distributions and that point to them in the jsdelivr
, unpkg
or main
fields of their package.json
files.* Unfortunately, not all modules are compatible: some rely on the built-in functions in Node.js that have no equivalent in the browser, and others don’t include an AMD file that require
can use.
Note
require
works with a subset of AMD modules that includes the vast majority of such modules: the strict specification is documented by d3-require, the module that powers Observable’s require
.
Import: a way to require ES6 modules
In addition to require
, which uses the widely-supported AMD standard, we also support dynamic import, a new way of requiring modules that aims to replace custom module loaders such as require
.
import
is a native browser feature that’s just now gaining adoption. It only works in the newest versions of Chrome, Safari, Firefox, and Edge. It also requires modules to be published in the ES6 module specification, which is still gaining adoption.
If the library is also published to npm, Skypack provides a fast CDN; otherwise, consider attaching a file.