Enable Node.js Integration in NW.js Renderer Windows and Package for Distribution
Enable Node.js in NW.js renderer windows, verify require() in DevTools, and package with nw-builder.
16 Apr 2026, 20:48 UTC

Problem and takeaway
Problem: An NW.js renderer window often loads HTML but throws require is not defined when a script tries to use Node.js built-ins, and an app that runs in development can fail after packaging because native modules were compiled for the wrong Node.js ABI (the compiled interface between a native module and the Node.js runtime).
Takeaway: Set nodeIntegration: true in the window section of package.json, confirm process.versions.node in DevTools before packaging, and rebuild any native modules against the exact NW.js Node.js release.
Prerequisites
- NW.js SDK or runtime installed for your development platform. The SDK build includes DevTools and debugging symbols.
- A project folder containing
package.jsonand at least one HTML entry point. - Node.js and npm installed to run the packager.
nw-builderinstalled as a development dependency:npm install nw-builder --save-dev. Run this in your project directory; no administrator permissions are required.
1. Configure package.json for Node.js integration
NW.js reads package.json to locate the application entry point and to configure each window. The main field names the HTML file the renderer loads. The window object controls appearance and whether Node.js APIs are available inside that renderer.
Create or edit package.json in the project root:
{
"name": "desktop-app",
"version": "1.0.0",
"main": "index.html",
"window": {
"title": "Desktop App",
"width": 1024,
"height": 768,
"frame": true,
"resizable": true,
"nodeIntegration": true
}
}
nodeIntegration: true allows renderer scripts to use require() and load Node built-ins and installed npm modules. If you set it to false, the renderer runs without direct Node access, and privileged operations require a separate bridge process. For a local desktop UI that needs file-system or process access, true is the simpler choice, but it also means any cross-site scripting vulnerability in the renderer can execute system commands. Only load trusted local HTML when this flag is enabled.
2. Verify Node.js access before packaging
Launch the app from the project directory using the NW.js runtime:
nw .
Run this command in the project directory. It requires no special permissions. When the window opens, open Developer Tools (DevTools; usually F12 or Ctrl+Shift+I), open the Console, and run:
console.log(typeof require);
console.log(process.versions);
Expected check: typeof require should print function, and process.versions.node should show a Node.js version string. Compare that Node string to the Node.js release bundled with your NW.js version. NW.js major versions track specific Chromium and Node.js releases, so this string confirms you are developing against the intended runtime.
3. Add a renderer script that uses Node
Create index.html if it does not exist:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Desktop App</title></head>
<body>
<pre id="output">Loading...</pre>
<script src="renderer.js"></script>
</body>
</html>
Create renderer.js:
const fs = require('fs');
const path = require('path');
document.getElementById('output').textContent =
'Node.js version: ' + process.versions.node + '\n' +
'Current directory: ' + process.cwd() + '\n' +
'Platform: ' + process.platform;
Reload the NW.js window. The console should show no errors, and the page should display the Node.js version, current directory, and platform. If you see require is not defined, confirm that nodeIntegration is set to true and that NW.js loaded the correct package.json.
4. Package for distribution
Use nw-builder to gather your application files, select an NW.js build per platform, and emit distributable archives or installers. Run from the project directory:
npx nw-builder --platforms win64,osx64,linux64 --version <nw-version> ./build
Replace <nw-version> with the NW.js major version you tested against. The exact flag names and supported target list depend on the packager version; confirm them in the nw-builder documentation before cutting a release. Output appears in the ./build directory by default, though the location can vary by packager version.
If your app uses native Node modules, they must be rebuilt for the exact NW.js Node.js ABI. A version mismatch causes require() to throw at runtime. Rebuild them against the NW.js headers before packaging, using the tooling recommended for your NW.js release.
5. Verify the packaged build
Extract or install the package for one target platform, then launch it outside the development runtime. Expected checks:
- The main window opens at the size and position defined in
window.width,window.height, and related fields. - The frame and resizable behavior match
window.frameandwindow.resizable. - Opening DevTools and running
typeof requirereturnsfunction. - Native modules load without an ABI error.
Limitations and recovery
- Security: Enabling
nodeIntegrationexposes the full Node.js API to renderer code. Do not load remote or untrusted content in a window with this flag enabled. - Runtime upgrades: Do not assume the newest NW.js release supports older app code. Test upgrades on a branch before changing the production runtime.
- Native modules: If
require()throws after packaging, the most likely cause is a native module built for a different Node.js ABI. Rebuild the module for the NW.js Node version or remove it if it is not needed. - Rollback: Because packaging writes to an output directory and does not modify your source code, rollback is deleting the output directory and rebuilding from the previous known-good
package.jsonand NW.js version.
If the packaged window fails to launch, run the unpackaged app with nw . again and compare process.versions between the development runtime and the packaged build. A mismatch indicates the packager pulled the wrong NW.js binary.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.