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.
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.
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.
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
.
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.
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
.
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
:
(
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.
(
async () => {
try {
const module = await require('non-existent-module');
} catch (error) {
console.error('Failed to load module:', error);
}
}
)();