Module import/export event listener

I've been musing lately on whether there are valid use cases for being able to listen for an es6 module when it is imported for the first time (which I don't believe is possible natively at the moment?).

globalThis.addEventListener('module.exports', function(e) {
    //data passed with event
    var path = e.detail.path; //access to module full path/url
    var exports = e.detail.exports; //access to promise resolving to module exports
    //do things with data
   //E.g. analyse module path to take action or handle exports outside of calling module
});

I was thinking of cases where it might be beneficial to do things with particular exports based on the type of module (based on its path), outside of the calling code. A central registry of different exports based on their file path (E.g. services vs UI components), for example.

Just interested whether anyone else sees any valid use cases?

More fundamentally is that there are currently no event listeners at all in tc39.es/ecma262. That pattern is from the web specs.

On a module load listener, I would imagine that this could be implemented as a plug-in for a bundler and published. To see how much use it gets and which patterns it enables.

As with all additions to ecmascript, the first step is: which problem is being solved, rather than what APIs to add :slightly_smiling_face:

Ah yes, hadn't noticed that at all!

To me it feels like a limitation not to be able to intercept module lifecycle events (loading/importing is the one I ran into an issue with, but perhaps there could be others), but as I couldn't find any real discussion of the topic, I thought I'd see whether anyone else actually saw problems with not being able to do so.

A plugin for a bundler does sound like a decent idea to see whether anyone would even make use of such a listener.

Why does it matter which module is importing it for the first time? There's not necessarily a guarantee in an application that it'll always be the same first-importer.

node has a feature like this for CJS, module.parent, and in practice it's turned out to be a very unreliable and brittle thing to rely on. Modules don't have a "parent", and the "first consumer" turns out not to be particularly valuable.

I don't think there was any mention of access to the 'parent'.

This sounds similar to webpack loaders, where loaders can be configured to only transform modules whose path matches a particular regex.

There is more of a limit to what can be done at runtime as the module namespace object is effectively frozen.

module.parent also tells you the identity/specifier of the module, which give you access anyways since you can require/import it from that.

The Compartments API is basically a module loader API that allows a program to virtualize the module loading logic. The proposal is in dire need of an update, but it is partially implemented by Moddable's XS engine.

Now I'm not sure if that would solve your use case as I don't know the problem you're trying to solve with a listeners API. One comment on that approach however, since the static module graph is resolved before any execution, I assume your listener would only deal with dynamic imports? If it was able to detect synchronous imports, that would make module evaluation TDZ even more of a can of worms.

1 Like