title: How to write a module that works with Node.js, RequireJS as well as without them
body: <p>I am working on a JavaScript library for <a href="https://github.com/highsource/jsonix" rel="noreferrer">JSON/XML processing</a>. My library works in browser as well as Node.js (with <code>xmldom</code> and <code>xmlhttprequest</code> modules).</p>
  
  <p>One of the users recently asked for RequireJS support. I have taken a look at the RequireJS/AMD thing and think it is a good approach so I'd like to provide this.</p>
  
  <p>However I'd like to retain the portability: my library must work in browsers (with and without RequireJS) as well as Node.js. And in the browser environment I don't depend on <code>xmldom</code> or <code>xmlhttprequest</code> since these things are provided by the browser itself.</p>
  
  <p><strong>My question is: how can I implement my library so that it works in browsers as well as in Node.js with an without RequireJS?</strong></p>
  
  <p>A bit of historyand my current solution</p>
  
  <p>I initially wrote my library for browsers. So it just created a global-scope object and put everything inside it:</p>
  
  <pre><code>var Jsonix = { ... };
  </code></pre>
  
  <p>Later on users asked for Node.js support. So I added:</p>
  
  <pre><code>if(typeof require === 'function'){
      module.exports.Jsonix = Jsonix;
  }
  </code></pre>
  
  <p>I also had to import few modules mentioned above. I did it conditionally, depending on whether the <code>require</code> function is available or not:</p>
  
  <pre><code>if (typeof require === 'function')
  {
      var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
      return new XMLHttpRequest();
  }
  </code></pre>
  
  <p>Now there's this story with RequireJS. If RequireJS is present then the <code>require</code> function is present as well. But module loading works differently, I have to use the <code>define</code> function etc. I also can't just <code>require</code> things since <code>require</code> has an async API in RequireJS. Moreover, if my library is loaded via RequireJS, it seems to process the source code and detects <code>require('something')</code> even if I do it conditionally like</p>
  
  <pre><code>if (typeof require === 'function' &amp;&amp; typeof require.specified !== 'function) ...
  </code></pre>
  
  <p>RequireJS still detects <code>require('xmlhttprequest')</code> an tries to load the corresponding JS file.</p>
  
  <p>Currently I'm coming to the following solution.</p>
  
  <pre><code>// Module factory function, AMD style
  var _jsonix = function(_jsonix_xmldom, _jsonix_xmlhttprequest, _jsonix_fs)
  {
      // Complete Jsonix script is included below 
      var Jsonix = { ... };
      // Complete Jsonix script is included above
      return { Jsonix: Jsonix };
  };
  
  // If require function exists ...
  if (typeof require === 'function') {
      // ... but define function does not exists, assume we're in the Node.js environment
      // In this case, load the define function via amdefine
      if (typeof define !== 'function') {
          var define = require('amdefine')(module);
          define(["xmldom", "xmlhttprequest", "fs"], _jsonix);
      }
      else {
          // Otherwise assume we're in the RequireJS environment
          define([], _jsonix);
      }
  }
  // Since require function does not exists,
  // assume we're neither in Node.js nor in RequireJS environment
  // This is probably a browser environment
  else
  {
      // Call the module factory directly
      var Jsonix = _jsonix();
  }
  </code></pre>
  
  <p>And this is how I check for dependencies now:</p>
  
  <pre><code>if (typeof _jsonix_xmlhttprequest !== 'undefined')
  {
      var XMLHttpRequest = _jsonix_xmlhttprequest.XMLHttpRequest;
      return new XMLHttpRequest();
  }
  </code></pre>
  
  <p>If I have <code>require</code> but not <code>define</code> then I assume this is a Node.js environment. I use <code>amdefine</code> to define the module and pass the required dependencies.</p>
  
  <p>If I have <code>require</code> and <code>define</code> thet I assume this is a RequireJS environment, so I just use the <code>define</code> function. Currently I also assume this is a browser environment so dependencies like <code>xmldom</code> and <code>xmlhttprequest</code> are not available and don't require them. (This is probably nor correct.)</p>
  
  <p>If I don't have the <code>require</code> function then I assume this is a browser environment without RequireJS/AMD support so I invoke the module factory <code>_jsonix</code> directly and export the result as a global object.</p>
  
  <p>So, this is my approach so far. Seems a little bit awkward to me, and as a newbie to RequireJS/AMD I'm seeking advise. Is it the right approach? Are there better ways to address the problem? I'd be grateful for your help.</p>