How to know whether a piece of JS is executed in an ES Module or a regular script?

Viewed 237

I want to know whether a piece of JavaScript is executed in an ES module or a simple script.

This is what I tried so far:

function isEsm1() {
  try {
    // Script gives a syntax error during parsing when script is not an esm
    return Boolean(import.meta.url); 
  } catch(err) {
    return false;
  }
}

function isEsm2() {
  // will always return false, because `eval` always seems to be executed in regular script context
  try {
    return eval('Boolean(import.meta.url)'); 
  } catch(err) {
    return false;
  }
}


function isEsm3() {
  // Of course doesn't work, but had to try 
  return 'meta' in import; 
}
2 Answers

Is the regular script executed in the browser or in another context?

In a browser, how about:

var anyvar = {};
var inModule = anyvar === window.anyvar;

If you're in a module, you are not declaring anything on the window...

In NodeJS you could do something similar with global or this:

let inModule = this === module.exports..

Did not try it yet.. but should work I guess...

After testing, just the check for this === undefined is enough to test if you're executing in or out of a module..

Inside a module, this is undefined (as per spec). In global scope this points to global this, which is the window object in the case of a browser context...

Thanks to the discussion in John Gorter's answer, I think we've found a way.

console.log('In module: ' + (this === undefined));

It's as simple as that. Inside a module (and only inside a module (I hope)), this will be undefined. I found it in the v8 documentation here: https://v8.dev/features/modules#intro

Related