Skip to content
On this page

Importing Libraries from NPM in Rational Notebooks

Rational notebooks allow you to leverage the vast repository of JavaScript packages in NPM (Node Package Manager). This guide will walk you through the process of importing these libraries into your Rational notebook using the require function.

Understanding NPM

NPM is the default package manager for the JavaScript runtime environment Node.js. It is a public repository where developers can share and borrow packages (reusable code modules). When you require a package in a Rational notebook, the system fetches it directly from NPM.

Requiring a Library from NPM

In Rational notebooks, the require function is used to import modules. There are several ways you can use require to import from NPM, depending on how much specificity you need.

A Module Name and a Version

You can specify the name of the package and the version you want to use. This is useful when you want to ensure that your notebook always uses the same version of a package, even if new versions are released.

javascript
moment = require('moment@2')

In this example, the notebook is requiring version 2.x.x of the moment date and time library.

A Module Name

If you don't specify a version, require will fetch the latest version of the package. This might cause your notebook to break if a new version introduces changes that are not compatible with your code.

javascript
moment = require('moment')

A Module Name, a Version, and a Path

Some packages may not expose the file you need as the default. In such cases, you can specify the file path after the package name and version.

javascript
d3v6 = require('d3@6/d3.min.js')

A URL

If a library is not available on NPM, or you want to load it from a different source, you can provide a full URL to require.

javascript
ganja = require('https://unpkg.com/ganja.js/ganja.js')

Multiple Inputs

If you need to import multiple packages or files, you can provide an array of strings to require. The function will return an object that combines the exports of all the specified packages or files.

javascript
d3AndTopojson = require(['d3', 'topojson'])

Using the Imported Libraries

Once you've imported a library, you can use it in your notebook like any other JavaScript code. If the library's content changes and require fetches a new version, any cells using the library will automatically update.

Understanding Require's Behavior

require fetches the specified packages from NPM and makes them accessible in the notebook. It relies on jsDelivr, a service that takes NPM modules and makes them accessible to browsers.

When you call require with a package name and version (for example, d3@7), it fetches the package from a URL like "https://cdn.observableusercontent.com/npm/d3@7.8.5/dist/d3.min.js". You can see the resolved URL by calling require.resolve.

javascript
require.resolve('d3@7')

Caveats and Requirements for Require

Not all NPM packages can be imported using require. Some packages rely on Node.js built-in functions that don't exist in the browser, while others don't include a file in the required format. If you're having trouble requiring a module, consider asking for help in the forum, or look for alternatives.

Understanding the Return Value of Require

The require function returns a Promise that resolves with the contents of the module being imported. A Promise in JavaScript represents a value which may not be available yet but will be resolved at some point in the future.

While most of the time you'll use require in a cell of its own and let Rational automatically handle the Promise resolution, there might be cases where you want to use require in the context of other code. In these situations, you need to manually handle the Promise.

To access the value a Promise resolves to, you need to await it. The await keyword pauses the execution of the function until the Promise is resolved. Note that to use await, the function itself must be an async function.

Here's an example of how to use require with await:

javascript
(
  async () => {
      const d3 = await require('d3');
      // Now you can use d3 in this function scope.
      console.log(d3.version);
  }
)();

In the case where require fails to load a module—for example, the module doesn't exist, or there's a network error—it will return a Promise that rejects with an error. You should use a try/catch block to handle potential errors when you await a Promise.

javascript
(
  async () => {
    try {
        const module = await require('non-existent-module');
    } catch (error) {
      console.error('Failed to load module:', error);
    }
  }
)();