Node.js Require Hook
node-hook is a low-level utility for intercepting and transforming JavaScript source code before it is loaded by Node.js's CommonJS `require` mechanism. It allows developers to register a synchronous function that receives the raw source and filename, returning a modified source string for immediate evaluation. The current stable version is 1.0.0, released in 2017. Due to its age and reliance on Node.js's CommonJS module loader, it is largely incompatible with modern ES Modules (ESM) environments. Its release cadence was infrequent, with the last update several years ago. Key differentiators include its direct manipulation of `Module._extensions['.js']` for simple, synchronous source transforms, unlike more complex bundlers or build tools, making it suitable for runtime code instrumentation or on-the-fly transpilation in legacy CommonJS applications.
Common errors
-
SyntaxError: Cannot use import statement outside a module
cause Attempting to use `import hook from 'node-hook';` in a CommonJS context or a file without `'type': 'module'` in `package.json`.fixUse the CommonJS `require` syntax: `const hook = require('node-hook');` -
TypeError: Cannot read properties of undefined (reading 'hook') at Object.<anonymous> (test.js:3:16)
cause Incorrectly trying to call `require('node-hook').hook()` as a function, or attempting to access `hook` before it's properly assigned from the module's export.fixAccess the `hook` function as a property: `const { hook } = require('node-hook');` or `const nodeHook = require('node-hook'); nodeHook.hook(...);` -
My transform function isn't being applied to subsequent `require()` calls for the same file.
cause Node.js caches modules after their initial `require()` call. Subsequent `require()` calls for the same file return the cached version without re-running transforms.fixTo ensure your transform is applied, clear the module from the `require.cache` before re-requiring: `delete require.cache[require.resolve('./your-module')];`
Warnings
- breaking Version 1.0.0 introduced breaking changes; however, the specific details beyond 'release 1.0.0 closes #11' are not documented. Users upgrading from pre-1.0.0 versions should review their usage patterns carefully. Given the project's age, this is primarily a historical note.
- gotcha Node.js caches compiled modules. If you apply a hook and then `require` the same file again, the cached version will be returned, and your transform function will not be re-applied. This can lead to unexpected behavior where changes aren't reflected.
- breaking node-hook operates exclusively on Node.js's CommonJS `require` mechanism. It is fundamentally incompatible with ES Modules (ESM) `import` statements and module loading processes. Attempting to use it in an ESM project or to hook ESM files will not work as intended.
- gotcha The project appears to be abandoned, with its last release in 2017. This means it receives no updates, bug fixes, or security patches. It may not work with newer Node.js versions or dependencies, and could pose a security risk due to unaddressed vulnerabilities.
Install
-
npm install node-hook -
yarn add node-hook -
pnpm add node-hook
Imports
- hook
import hook from 'node-hook';
const hook = require('node-hook'); - hook.hook
const hook = require('node-hook').hook();const { hook } = require('node-hook'); - hook.unhook
const { unhook } = require('node-hook');
Quickstart
const { hook, unhook } = require('node-hook');
const path = require('path');
const fs = require('fs');
// Create a dummy file to be required
const dummyFilePath = path.join(__dirname, 'dummy.js');
fs.writeFileSync(dummyFilePath, 'module.exports = { message: "Hello from dummy!" };');
console.log('--- Registering hook ---');
// Register a transform function to log the filename and modify source
function logAndModifySource(source, filename) {
if (filename === dummyFilePath) {
console.log(`[HOOK] Processing: ${filename}`);
return `console.log('Transformed source for ${path.basename(filename)}');\n${source}\nmodule.exports.transformed = true;`;
}
return source;
}
hook('.js', logAndModifySource);
console.log('--- Requiring dummy.js ---');
const dummyModule = require('./dummy');
console.log('--- Dummy module content ---');
console.log(dummyModule);
console.log('--- Unhooking .js ---');
unhook('.js'); // Removes the transform
console.log('--- Requiring dummy.js again (should use cached version) ---');
const dummyModuleCached = require('./dummy');
console.log(dummyModuleCached);
// Clean up dummy file
fs.unlinkSync(dummyFilePath);