How can I tell that a script written in node is being called by require?
From the node docs:
Accessing the main module
When a file is run directly from Node, require.main is set to its
module. That means that you can determine whether a file has been run
directly by testing
require.main === module
For a file foo.js, this will be true if run via node foo.js, but false
if run by require('./foo').
Because module provides a filename property (normally equivalent to
__filename), the entry point of the current application can be obtained by checking require.main.filename.
You can check property parent of module object. If your module called by require module.parent will return caller module, otherwise module.parent is null.
Related
According to the description of require.cache
Modules are cached after the first time they are loaded. This means
(among other things) that every call to require('foo') will get
exactly the same object returned, if it would resolve to the same
file.
But When I've tested it in my node REPL, require.cache already has its object before require.
// test code
const utilsPath = require.resolve('../utils')
// logging the cache before require utils module.
console.log('-----')
console.log(require.cache[utilsPath])
console.log('-----')
const utils = require('../utils')
The console output is a Module object, and its key is the utilsPath.
How can require cache has that before require the corresponding module?
I've also tested with another module, but in that case, require cache was empty.
Any advice would really be appreciated!
The js_of_ocaml documentation says about making a Node.js module:
Js.export and Js.export_all will export a value to module.exports if it exists.
What I'm confused about is the "if it exists" part. How do I make sure that the module def exists? i.e. if I'm making an OCaml library that I'd like to be able to import from JavaScript (TypeScript actually), how can I make sure that I get such a module as the output of js_of_ocaml?
If module.exports exists, a value is exported as node module.
And if module.exports doesn't exists (on web browser for example), a value is exported as global variable.
It seems that in Node.js 'require' and 'module.require' are not only separate objects but also different types of objects. 'require.resolve' exists but 'module.require.resolve' does not.
Is there any way to call resolve on module.require?
The reason I would like to do that is I would like to call require.main.require.resolve() to see what require.main.require
resolves a given path to.
Here's what I can find out to explain.
require.main gets you the module object for the script that was run first in this node.js process.
require.main.require gets you a function you could use to load scripts as if you were in that main script.
require.main.require does not have a .resolve() method. While require.main.require does get you a require function, as you have found it is not the exact same object that you get when you are in a module itself. It is just a function and appears to have none of the properties that the require object has in your own module.
The require object in your own module gets created by a special function called makeRequireFunction() in the loader (see source code here). That's where the other properties are added to it. But, the require.main.require is the same as process.mainModule and is just the require function by itself, not that special object.
A work-around would be to export resolve() from your entry script then access that exported function from the other script.
In your main module, you could put this:
module.exports.resolve = require.resolve;
Then, you could access that elsewhere with:
require.main.exports.resolve(...);
I have two js files on my node server that require each other.
both have objects that are exposed via the module.exports mechanism.
1st file is located under bl/commands.js and uses:
var smUtil = require('./../utils/smUtil');
2nd file is located under utils/smUtil.js and uses:
var commands = require('./../bl/commands');
When a function runs from smUtil.js and uses some properties of commands.js it seems like command is an empty object and the import was not successful.
Here is the catch, when i remove the require of smUtil form inside commands.js everything works, which makes me think that i'm doing a newbe mistake.
Any thoughts?
Node.js documentation about circular dependencies
You are absolutely right that empty objects are returned.
To Quote Node.js documentation
When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.
A solution could be to create a separate file to require both the files there and instantiate that file to avoid the circular dependency.
The specific solution which solved my problem was to place var smUtil = require('./../utils/smUtil'); Underneath the module.exports inside commands.js.
However i feel like this solution is not the best one out there.
Thanks to the author of:
coderwall.com/p/myzvmg/circular-dependencies-in-node-js
I was looking in the node.js module documentation, and noticed that each module has a property- module.parent. I tried to use it, but got burnt by the module caching- module.parent only ever seems to the module that first require()'d it, irrespective of current context.
So what is the usage of it? Is there any other way for me to get a reference to the current require()ing module? Right now I'm wrapping the module in a function, so that it is called like:
require("mylibrary")(module)
but that seems sub-optimal.
The "parent" is the module that caused the script to be interpreted (and cached), if any:
// $ node foo.js
console.log(module.parent); // `null`
// require('./foo')
console.log(module.parent); // `{ ... }`
What you're expecting is the "caller," which Node doesn't retain for you. For that, you'll need the exported function you're currently using to be a closure for the value.
There is a workaround for this. Node adds a module to the module cache before it finishes loading it. This means that a module can delete itself from the module cache while it's loading! Then every time the module is require'd a new instance of the module is loaded.
Magic.js
console.log('Required by ' + module.parent.filename);
delete require.cache[__filename];
Module1.js
//prints "Required by Module1.js"
require('./Magic');
Module2.js
//prints "Required by Module2.js"
require('./Magic');
Of course the side-effect of this is that your module is no longer a singleton, so you have to code Magic.js with that in mind. If you need to store global data you can always keep it in a require()'ed module that doesn't delete itself from the cache.
Update for 2022
Note the technique described above doesn't work for ES Modules included with import. As far as I know there is no good way to detect the importing ES Module.