@benjamnWill Meteor 1.3 compile Meteor packages into code that follows the CommonJS module semantics? So they just use require to get their dependencies. And they export via module.exports. This is would be very useful to use standard testing tools, like Jest with Wallaby for unit testing. Otherwise I’m forced to load all Meteor packages before I can run the tests and that’s slow.
I understand that some Meteor package code is coupled to Meteor. But that wouldn’t be a big problem, because I can mock packages.
Well, I think BABEL will do this, just try it: https://babeljs.io/repl/. Meteor’s module system from 1.3 will then use the output, which ist based on require syntax. Please correct me, if I’m wrong.
I think right now in the beta, packages still get their dependencies via the Package global. You can see that when you look at the built files in .meteor/local/build. So the Meteor build tool does some transformation and concatenation after Babel compiling.
Semantic UI is a Meteor package, and is clearly imported as a numer of modules… But that might be a special case, as SemanticUI generates client side files…?
Packages still need to be backwards compatible, so the final linked version (try view-source on a package’s JS in 1.3) is still an IIFE with regular Meteor imports (Package global, local vars for file-level “globals”), etc.
However, if your package doesn’t use the old API - api.use()/export() - and instead relies solely on import and export, I think you’ll be ok. I never tried though It will still be inside an IIFE and you might need to stub a Package global to avoid a ReferenceError, but it uses the new meteorInstall for deps, which is based on CommonJS - each file is wrapped in a function(require,exports,module) and receives deps via this require.
This is an excellent & accurate summary, @gadicc! Thanks for making my job easier
It is definitely true that Meteor package code, though implemented using a CommonJS module system, is eagerly required before your application code has a chance to import it.
While that behavior is important for backwards compatibility, Meteor 1.3 is introducing a new package.js API, namely api.mainModule, so we might have an opportunity to allow lazy Meteor packages in a backwards compatible way. Specifically, api.mainModule could take an options object, like so:
If the main module is lazy, we would avoid emitting an eager require("/node_modules/meteor/<package name>/client.js") call at the end of the package bundle, and your application code would become responsible for importing meteor/<package name> when needed.
Of course this would mean the package might never be loaded at all, but that sounds more like a feature than a pitfall. Also, you could still define other eager entry point files using api.addFiles.
I think based on that information and what I have seen in the code, the Jest auto-mocking feature will not work with Meteor packages, because it only works with CommonJS modules.
It would be nice if the build tool could output Meteor packages as real CommonJS modules at some point, just for the use case of using those packages outside of a Meteor app.
For now I will just load all packages like the Meteor start script does and run the tests after the packages have been loaded. This is a bit slower, but works ok.