80

In Node.JS document, I found a sentence said

When a file is run directly from Node.js, require.main is set to its module. That means that it is possible to determine whether a file has been run directly by testing require.main === module.'

I want to ask what is the main here, I can not find definition of this main in source code, can anyone help, thanks!

Or B
  • 1,857
  • 15
  • 22
phaneven
  • 887
  • 2
  • 9
  • 10

4 Answers4

103

require is a function. .main is a property on that function so you can reference require.main. That part of the doc you are referring to says that you can write code like this:

if (require.main === module) {
     // this module was run directly from the command line as in node xxx.js
} else {
     // this module was not run directly from the command line and probably loaded by something else
}

module in that above code is a variable that is passed to all modules that are loaded by node.js so that code basically says that if require.main is the current module, then the current module is what was loaded from the command line.

The code for setting that property is here: https://github.com/nodejs/node/blob/master/lib/internal/modules/cjs/helpers.js#L44.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks for your answer, but I cannot find the .main property in the Module.prototype.require in module.js file. I am just curious about where the source code define the .main property. – phaneven Jul 17 '17 at 06:21
  • @jfriend00 The link to the code returns 404. Can you please update the link ? thanks – Nelson Teixeira Sep 20 '18 at 16:46
  • 1
    @NelsonTeixeira - Updated the link in the question. Links like that are specific to a general organization of the nodejs code in Github and will change over time. In this case, the module loading code was reorganized in the repository when code for the ES6 loader was added which is what caused this source file to get moved in the repository. – jfriend00 Sep 20 '18 at 16:52
  • I understand, but thought this was important enough, and perceived that you have the in-depth knowledge of Node's source code in order to make it an easy task. I was correct in my assumptions. :) Thanks. – Nelson Teixeira Sep 20 '18 at 16:57
  • 4
    How to detect the same in es6 modules? – explorer May 13 '19 at 03:56
  • I added an [example below](https://stackoverflow.com/a/60309682/524518) that shows an alternative to `process.main` when using ES modules with Node.js. – Tim Schaub Feb 19 '20 at 21:42
68

When running ECMAScript Modules with Node.js, require.main is not available. As of Node 13.9.0, there is not a succinct way to determine whether a module was run directly or imported by another module. It is possible that an import.meta.main value will allow for such a check in the future (comment on the modules issue if you think this makes sense).

As a workaround, it is possible to check if the current ES module was run directly by comparing the import.meta.url value to process.argv[1]. For example:

import { fileURLToPath } from 'url';
import process from 'process';

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  // The script was run directly.
}

This does not handle the case where the script is called without the .js extension (e.g. node script instead of node script.js). To handle this case, any extension could be trimmed from both import.meta.url and process.argv[1].

The es-main package (caveat: I am the author) provides a way to check if an ES module is run directly, accounting for the different ways it can be run (with or without an extension).

import esMain from 'es-main';

if (esMain(import.meta)) {
  // The script was run directly.
}
Tim Schaub
  • 6,722
  • 1
  • 26
  • 17
  • 5
    This information is surprisingly hard to find! – mrdecemberist May 20 '21 at 13:09
  • 1
    This failed for me when including an npm package from a relative path on the local hard drive. I believe there is a symbolic link involved, which causes `dirname(fileURLToPath(import.meta.url))` to be different than `process.argv[1]` – Trevor Jul 14 '22 at 07:19
6

Quite late me answer, but i leave it here for reference.

  1. When a file is the entry point of a program, it's the main module. e.g. node index.js OR npm start, ​the index.js is the main module & the entry point of our application.

  2. But we might need to run it just as a module, and NOT as a main module. This can happen if we require the index.js like so:

node -e "require('./index.js')(5,6)"

We can check if a file is the main module in 2 ways.

  1. require.main === module
  2. module.parent === null

Lets say that we have a simple index.js file, that it either console.log() ,when it is the main module, or it exports a sum function, when it is not the main module:

if(require.main === module) {
 // it is the main entry point of the application
 // do some stuff here
 console.log('i m the entry point of the app')
} else{
 // its not the entry point of the app, and it behaves as 
 // a module
 module.exports = (num1, num2) => {
   console.log('--sum is:',num1+num2)
  }
 }

Ways to check the above condition:

  1. node index.js --> will print i m the entry point of the app
  2. node -e "require('./index.js')(5,6)" --> will print --sum is: 11
Theo Itzaris
  • 4,321
  • 3
  • 37
  • 68
3

For ECMAScript modules, or files with .mjs as its extension I use a simpler version of it:

if (import.meta.url.endsWith(process.argv[1])) {
  // run the app
}
Mestre San
  • 1,806
  • 15
  • 24