Bundling Dependencies
If you’re not familiar with the idea, module bundling is:
[The] process of stitching together a group of modules (and their dependencies) into a single file (or group of files) in the correct order.
There’s a healthy ecosystem of module bundlers designed for JavaScript projects, especially projects focused on web development. Even though Nova extensions don’t target a web browser, they do use a JavaScript extension runtime, which means we can use the same bundlers to bring external modules to our projects.
In this guide we’ll use Rollup.js, but if you’re familiar with other bundlers like Webpack or Browserify, the same principles will apply.
Installing devDependencies
Our top-level project will use the rollupjs
package and a handful of Rollup plugins:
so let’s install those now using NPM:
npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs
"devDependencies": {
"@rollup/plugin-commonjs": "^11.0.1",
"@rollup/plugin-node-resolve": "^7.0.0",
"rollup": "^1.30.1"
},
"dependencies": {
"chroma-js": "^2.1.0"
},
Configuring Rollup.js
Next, we need to tell Rollup where to look for our entry point script, and what we want it to do at build time.
Create a new file rollup.config.js
a the root of your top-level project:
(nova-novachrome)
├── ...
├── package.json
├── package.lock.json
├── README.md
└── rollup.config.js
then open it and paste the following:
const commonjs = require( "@rollup/plugin-commonjs" );
const resolve = require( "@rollup/plugin-node-resolve" );
module.exports =
{
input: "src/Scripts/main.js",
plugins: [
commonjs(),
resolve(),
],
output: {
file: "Novachrome.novaextension/Scripts/main.dist.js",
format: "cjs"
},
}
What does this do?
Our configuration tells Rollup to:
- Begin by looking in our source script
src/Scripts/main.js
- Convert any CommonJS-style
require
statements it encounters to a format Rollup understands - Use
node_modules
to resolve any dependencies - Create
main.dist.js
as the output file inside our extension bundle using the CommonJS format
In a nutshell, we’re compiling our source file and its external dependencies into a single file inside our extension bundle in a format that Nova supports.
Let’s take it for a spin! Open a new Local Terminal tab and run the following command:
$ npx rollup -c
src/scripts/main.js → Extension.novaextension/scripts/main.dist.js...
created Novachrome.novaextension/scripts/main.dist.js in 334ms
If necessary, activate the extension again (Extensions > Activate Project as Extension) then open the extension console:
#663399
It worked! We successfully bundled imported chroma-js
into our main.js
source file:
const chroma = require( "chroma-js" );
console.log( chroma("#36036a").brighten().hex() );
and compiled it into our extension bundle.
Developing a Workflow
It’s convenient to work in a source file, compile into the extension bundle, and see things work as when the extension automatically reloads.
However, editing source files, switching to a terminal, and running npx rollup -c
every time we want to see a change is tedious.
Here are some tips for how to make development a little smoother.
NPM Scripts
Because our top-level folder is an NPM project, we can use all the same tools we’d use during development on non-Nova extension projects.
Let’s install onchange, a package that will watch for changes on disk:
npm install --save-dev onchange
Next, open package.json
and add two new scripts, build
and watch
:
"scripts": {
"build": "npx rollup -c",
"watch": "onchange -i \"src/**/*.js\" -- npm run build"
},
Switch to a local terminal and run the watch
script:
$ npm run watch
> nova-novachrome@0.1.0 watch /Users/ashur/Developer/nova-novachrome
> onchange "src/**/*.js" -- npm run build
Make a change in src/Scripts/main.js
:
chroma.temperature(3500);
and take a peek at the extension console:
#ffc38a
Our watcher sees the change, rebuilds our extension source, causing Nova to reload the extension.
- Next…
- Part 4: Nova Run Tasks
- Previously…
- Part 2: Structuring Your Project