Search code examples
javascriptmeteorcommonjs

Export in an if statement using meteor


it is fairly easy to import a file within an if statement like so:

import { Meteor } from 'meteor/meteor';

if (Meteor.isServer) {
  const thing = require('./blah').default;
}

However, what I am wondering is if you can export a default member of a module within an if statement without binding it to the global scope or window

if (Meteor.isServer) {
  export serverOnlyFunction = require('./blah').default;
}

How would this be accomplished in meteor?


Solution

  • This is not possible as you've written it, since exports must be defined at the top level (from §A.5 of the spec). This is related to how modules are handled when lazy-loading or circular dependencies occur and the code can't be executed during or before loading.

    You can avoid this mess entirely by exporting the branch, rather than exporting from within a branch:

    export function getTheFunction() {
      if (Meteor.isServer) {
        return serverOnlyFunction;
      } else {
        return functionForEverybody;
      }
    }
    

    Alternatively, a wrapper function will work just as well:

    export function wrapTheFunction(...args) {
      if (Meteor.isServer) {
        return serverOnlyFunction.apply(this, args);
      } else {
        return functionForEverybody.apply(this, args);
      }
    }
    

    If you're using exports directly without the ES6 keyword, you could assign from within the branch:

    if (Meteor.isServer) {
      module.exports = serverOnlyFunction;
    } else {
      module.exports = functionForEverybody;
    }
    

    But, unless you're stuck on ES5, this is poor practice. Exporting a function able to decide is a far more robust solution.

    Secondly:

    import { Meteor } from 'meteor/meteor'; // <- is an import
    
    if (Meteor.isServer) {
      const thing = require('./blah').default; // <- is *not* an import
    }
    

    require is not an import. They are two very different things with very different behavior. Furthermore, require is a runtime call made to an API provided by the runtime (node or requirejs) and return synchronously.

    The correct ES6 equivalent would be:

    if (Meteor.isServer) {
      System.import('./blah').then((thing) => {
        // do something with thing
      });
    }