This is a bit of an aside (though related), but the vaunted static analysis “enabled” by ES modules has currently got a nuclear-sized hole in it. I don’t see it allowing full static analysis that would be of great use by things-that-have-to-work until all non-statically analyzable things disappear from the scene (maybe in 2026?).
I am currently working on a tool that “simply” needs to be able to determine the exports of all files that could be imported into a module. It needs to do this during development, i.e. without running the code, i.e. it needs to be able to statically analyze the exports of everything that the application might be able to access.
It simply isn’t possible at this stage of the game to achieve this with 100% accuracy even with a pure ES module. The proverbial straw in the ES module specification is that keeps even some ES modules from being statically analyzable is
export * from 'x';. If ‘x’ is anything not statically analyzable (a CommonJS module for example), then the exports of the module using that statement are not statically analyzable.
This makes it impossible to consistently accomplish some pretty simple (and common in other languages) development-time activities. For example, in the following code, whether yStuff.hello exists cannot be determined by your editor while editing the file ‘x’ and a “goto” hello feature can’t be implemented.
// let module 'z' be from some other module system that can't be statically analyzed
// in ES module 'y'
export * from 'z';
// in ES module x
import * as yStuff from 'y';
Very few npm packages are currently statically analyzable. Even if they’ve adopted ES modules, the package.json leads you to the transpiled main instead of the true source ES module.
This is where the Meteor package system is ahead of npm. We have an interface definition (as given by the api.exports) that can be utilized to describe older package interfaces.
I hope Ben somehow convinces the npm community to add some equivalent of this to npm’s package.json before we go there. It would be very helpful to future development tools to be able to automatically determine the interface to a package. They can’t exactly read the README. A Meteor-specific extension to package.json doesn’t cut it. It should be something the whole community uses.
If we don’t get some means of defining a package interface added to package.json (and used), then the more npm we adopt, the less statically analyzable our code becomes. The only reason we might not be screaming about this is we haven’t had the time to evolve development tools (editor plugins for example) that use our package definitions to give us advanced features.
Ok, so yeh, that was a rant based on frustration.