How require and module.exports in node works

Nikhil Vijayan
Makers
Published in
2 min readAug 25, 2020

--

I’ve always wondered how you always have access to require and module.exports in any .js files running with node. I recently found something cool.

If you console.log arguments in a file, and run it with node. For eg:

// someFile.js
console.log(arguments);

We actually get arguments:

[Arguments] {
'0': {},
'1': [Function: require] {
resolve: [Function: resolve] { paths: [Function: paths] },
main: Module {
id: '.',
path: '/someFolder',
exports: {},
parent: null,
filename: '/someFolder/someFile.js',
loaded: false,
children: [],
paths: [Array]
},
extensions: [Object: null prototype] {
'.js': [Function],
'.json': [Function],
'.node': [Function]
},
cache: [Object: null prototype] {
'/someFolder/someFile.js': [Module]
}
},
'2': Module {
id: '.',
path: '/someFolder',
exports: {},
parent: null,
filename: '/someFolder/someFile.js',
loaded: false,
children: [],
paths: [
'someFolder/node_modules',
'/Users/username/node_modules',
'/Users/node_modules',
'/node_modules'
]
},
'3': '/someFolder/someFile.js',
'4': '/someFolder'
}

Every time you run a file using node (eg: node someFile.js), the file is loaded inside an IIFE ( immediately invoked function expression).

and the function looks like this:

(function (exports, require, module, __filename, __dirname)())

exports is essentially an alias or a reference to module.exports, which is why you can do this:

exports.foo = () => console.log("foo"); // OK

but not this:

exports = () => console.log("foo"); // NOT OK

Note: I learned this thanks to Sameer Buna’s “You don’t know node” talk from ForwardJS San Francisco 2017.

Originally published at https://nikhilvijayan.com.

--

--