Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`if __name__ == '__main__'` equivalent in javascript es6 modules

Is it possible to check if JavaScript file is being run directly or if it was required as part of an es6 module import.

for example a main script is included.

// main.js
import './other';

if (mainTest){
  console.log('This should run');
}

which imports a dependency.

// other.js
if (mainTest){
  console.log('This should never run');
}

including <script src=main.js></script> should result in the console message from main.js but not other.js.

I found the answer to this question with regards to node, but I am interested specifically for es6 imports

like image 728
Peter Saxton Avatar asked Jan 17 '16 19:01

Peter Saxton


1 Answers

An alternative for ES6 modules is now supported in Node. Using the new import.meta builtin. (Don't forget to set "type": "module" in package.json.)

Example

// main.js
import "./lib.js"
import { fileURLToPath } from "url";

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  console.log("I print to stdout!");
}
// lib.js
import { fileURLToPath } from "url";

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  console.log("I don't run, because I'm an imported module.");
}

$ node main.js output:

I print to stdout!

Utility function

I like to just import { isMain } from "./lib/utils.js" and pass import.meta.url to isMain().

import { argv } from "process"
import { fileURLToPath } from "url"
/**
 * Check if a module is the main module launched with the node process.
 * Meaning the module is NOT imported by another module,
 * but was directly invoked by `node`, like this: `$ node main.js`
 *
 * @example
 * ```js
 * // main.js
 * import lib from "./lib.js"
 * import { isMain } from "./utils.js"
 *
 * if (isMain(import.meta.url)) {
 *   console.log("I print to stdout")
 * }
 *
 * // lib.js
 * import { isMain } from "./utils"
 *
 * if (isMain(import.meta.url)) {
 *   console.log("I don't run, because I'm an imported module")
 * }
 * ```
 *
 * @param {string} moduleUrl needs to be `import.meta.url`
 * @returns {boolean} true if the module is the main module
 */
export function isMain(moduleUrl) {
  const modulePath = fileURLToPath(moduleUrl)
  const [_binPath, mainScriptPath] = argv
  return modulePath === mainScriptPath
}
like image 111
Junaga Avatar answered Oct 03 '22 22:10

Junaga