If we limit the scope to only app code on the server, it might not be too much work to add an experimental mode for native ESM. This doesn’t have to be part of Meteor 3. If we make it optional, we can add it in 3.x and iterate on it. There would be many breaking changes with native ESM.
Some of the things involved would be:
- updating import scanner to handle ESM
- not linking or having a simplified linking process
- changing the boot process
- making sure source maps on the server still work correctly
- the current implementation of
Assets
requires there to be an app scope, which there wouldn’t be with ESM - allow app code to import packages in a way that live bindings still work
- figure out how to handle packages and apps importing the same npm package to avoid having multiple instances of it where Node wouldn’t
- change how core-runtime detects when all code is loaded
- add a resolve hook so Node can find the Meteor packages and the app’s npm dependencies
The more interesting part is the client. For small apps, using native ESM might work, but the loading time scales with the number of modules, so at some point it becomes too slow. There’s also a number of features missing in ESM that Meteor would be expected or required to have. I’ve been thinking about this for a while. When I find the time, I will write a post describing the details, different options, trade-offs, what other bundlers have done, etc.
Three of the goals we would definitely have are:
- reasonably fast loading time even for apps with 10,000’s of modules
- Consistent behavior with the server’s module system
- Support for npm packages that use commonjs
I don’t think Meteor’s current module system is that outdated. If we designed a new module system today, it might look very different, or, depending on the goals, features, and the trade offs you were willing to make, you might end up with a very similar design. Some new projects, such as Turbopack or bun, have many similarities with Meteor’s module system. Having said that, I am very interested in alternative designs that have the same benefits of the current system and minimize the issues with it (for example: bundle size, build time complexity, runtime complexity, some core packages unable to use modules). Since we would need the client and server module systems to behave consistently, while experimenting with native ESM would be a good time to explore this.
Before investing in native ESM, it might be good to fix the two main issues with Meteor’s current module system:
- there is one code path left in reify that we never optimized, and in some cases can add a few seconds to the page load time
- update Meteor’s resolver to support the package.json exports field. This probably will be needed even if we switch to native ESM