Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rebuild node.js addon when source changes

I have a node.js app and I have created a native addon. (In case you need background info, native addons for node.js can be created like this).

In my development environment I want it to watch source files (these are C++ source files, in this case) and automatically rebuild my addon when the C++ source files change, and also automatically restart the node application after the build completes.

I'm certain there's more than one way to accomplish this, but I went down the road of trying nodemon. But I couldn't figure out how to get nodemon to wait for the build to finish before restarting the application.

I figure npm can probably do this itself too with a script, perhaps with some kind of a watch package. So I'm open to alternative approaches if there's something easier.

So when any of my source files change, really all I need is for node-gyp build to run at the right point in the restart workflow (stop node, recompile, restart node). Right now it rebuilds the addon and restarts the application without waiting for the build to complete, and that's undesirable.

Here's my nodemon.json file:

{
  "watch": [
    "addon/"
  ],
  "ignore": [
    "addon/build/"
  ],
  "events": {
    "restart": "cd addon && node-gyp build"
  },
  "ext": "js,json,cc,h"
}

This doesn't work because the "restart" is like an event, in that my script that runs node-gyp fires and executes, but it doesn't block restarting until the build is finished.

I was hoping it would work more like middleware, where it would run the build script after the app is terminated, but before it restarts the app. I also consulted this relevant nodemon issue, but there's no concrete suggestion there about how to make that happen.

I need to change something so that the rebuild (node-gyp step) will happen automatically when the source changes and then restart nicely.

Note: Later I'll restructure it so that it only rebuilds the addon when the relevant C++ source files change, and just restarts the app when .js files change without rebuilding the C++ addon, but first I need to figure out getting the node-gyp build step to happen at the right time.

like image 544
Wyck Avatar asked Apr 16 '18 04:04

Wyck


1 Answers

I solved this by having nodemon use the -x option to run npm. Then the npm script can execute the build and run scripts sequentially.

Here's the relevant part of my package.json:

"scripts": {
  "dev": "nodemon -x \"npm run buildrun\"",
  "buildrun": "npm run build && npm run server",
  "build": "echo Building Addon && cd addon && node-gyp build",
  "server": "nodemon server.js",
}

You kickstart this by running npm run dev.

dev runs nodemon with the -x option and the command is npm run buildrun. Then nodemon restarts the npm buildrun script every time code changes. This was the main part I had trouble figuring out.

To explain the rest, the buildrun script runs two scripts back to back. The first one (build) builds the addon and the second one (server) runs the server.

The server script actually runs nodemon as well: it runs another nodemon to run the server script with nodemon server.js.

Technically, by having npm calling nodemon again (with the right configuration files, different arguments and context) nodemon could watch a different piece of the codebase and restart a different part of the system (e.g., watch just the server code without rebuilding the whole addon, which is what my actual code does.)

By calling nodemon with the -x option and having the entire build-and-run script get restarted when code changes, I was able to sequence the actions to get nodemon to first build the addon, wait for the build to complete, and then run the server.

This nodemon -x \"npm ...\" technique wasn't obvious to me at first and it actually took me half a year to come up with this solution. So, I'm sharing this because other people may find this technique useful.

like image 53
Wyck Avatar answered Nov 03 '22 01:11

Wyck