NodeWebKit Renderer 'require is not defined': A Diagnostic Guide
A systematic diagnostic guide for missing Node.js APIs in NodeWebKit renderer processes, covering configuration flags, preload scripts, bundler interference, and version-specific defaults.
23 Jun 2026, 14:49 UTC

The renderer console throws require is not defined, and every Node API your page script depends on is missing. The useful takeaway: in NodeWebKit, Node access in the renderer is a window-creation decision, not a runtime toggle. If require is absent, the window was built without Node integration, a command-line switch overrode it, or your bundler stripped the globals before the page ever loaded.
Recognizable Condition
The renderer process—the Chromium page context—throws ReferenceError for require, module, __dirname, or process. Node APIs work in the main process (for example, fs in the entry script) but are absent from page scripts. The failure may appear only after packaging, or only in specific windows while others work correctly.
Cause and Diagnostic Table
| Observable Symptom | Likely Cause | Diagnostic Signal |
|---|---|---|
require is not defined in every renderer window | Node integration disabled at window creation or default overridden | console.log(typeof require) returns "undefined" |
| Node APIs vanish only in production build | Bundler replaces Node built-ins with browser shims | Build logs warn about unresolved fs, path, or require |
| One window has Node access, another does not | Per-window preferences not set consistently | Compare window options across all creation calls |
| Error appears after adding a startup flag | Command-line switch disables Node integration | Remove suspect flags and retest |
Ordered Checks
Check 1: Confirm the runtime state
Open the renderer's DevTools console and run:
console.log(typeof require);
console.log(typeof process);
When Node is available, require should report "function" and process should report "object". If require is undefined, Node is blocked in that context.
Check 2: Inspect window creation options
Locate every call that opens a renderer window. For NW.js versions that accept webPreferences, verify that nodeIntegration is explicitly enabled. Changing this after the window exists has no effect; it must be present when the window is created.
Check 3: Rule out command-line overrides
Review the chromium-args array in package.json and any wrapper scripts. A switch that disables Node integration will override programmatic settings. If you suspect the flag is not being honored, launch the app with --debug-brk and attach a debugger to inspect the window's preferences before the page loads.
Check 4: Validate preload script wiring
If you rely on a preload script to expose Node APIs, confirm the path resolves correctly relative to the app root, the script is listed in the window options, and no bundler transformed the preload into a browser-only bundle.
Check 5: Audit the bundler configuration
If the app is built with Webpack, Rollup, or similar, inspect the renderer bundle. Bundlers often target the browser and stub Node globals. Look for configuration that marks fs, path, or other built-ins as empty or fallback modules.
Check 6: Verify NW.js version behavior
NW.js changed renderer security defaults across major versions. Confirm which version your package.json pins, then verify the expected default for that line. Older 0.12.x releases enabled Node in renderers by default; later versions tightened defaults and may require explicit opt-in.
Fixes Tied to Findings
If Check 1 shows require is undefined and Check 2 finds Node integration disabled: Set nodeIntegration: true in the window's webPreferences at creation time. Risk: this grants the page full Node API access. Do not enable it if the renderer loads remote or third-party content.
If Check 3 finds a conflicting command-line switch: Remove the switch from chromium-args or the launch script. Re-test locally before repackaging.
If Check 4 finds a broken preload reference: Use an absolute path constructed with path.join(__dirname, 'preload.js'). Ensure the preload script is not processed as a browser bundle.
If Check 5 finds bundler interference: Configure the renderer bundle to treat Node built-ins as external. Split the build so that renderer code targeting the DOM does not import Node modules directly; route those calls through a preload or main-process bridge.
If Check 6 finds a version mismatch: Align development and production environments on the same NW.js version. Consult the migration notes for the specific version jump.
Escalation Criteria
Escalate to an upstream issue or senior engineer when all checks pass, nodeIntegration is confirmed enabled, yet require remains undefined; when the failure is reproducible only on a specific OS or NW.js patch version; or when enabling Node integration causes a renderer crash rather than a clean ReferenceError. When escalating, include the NW.js version, OS, minimal package.json, the window creation snippet, and the exact console output.
Limitations and Verification
Enabling nodeIntegration expands the attack surface. If the renderer displays untrusted content, keep it disabled and use a preload script with a narrow, explicit API surface instead. The flag is read at window creation; toggling it later in the page lifecycle will not retroactively inject Node globals. Bundler fixes require a rebuild; a hot reload may not reflect the new externals configuration.
After applying a fix, open the renderer, launch DevTools, and run:
console.log(typeof require === 'function' && typeof process === 'object');
A result of true confirms Node APIs are available in that renderer context. For a production check, load the packaged app and repeat the same console test.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.