6

So I'm trying to set up Typescript and Chutzpah for testing purposes. Typescript is set up to output in this format:

define(['require', 'exports', './someModule'], function(require, exports, someModule) {
    //examplecode
});

Which works fine, the problem occurs when someModule is actually a directory with an index.js.

/app
  app.js
  /someModule
    index.js

require.js is unable to resolve someModule in this way and the test fails.

Is there any way to tell require.js that this is a module?

Devan Buggay
  • 2,717
  • 4
  • 26
  • 35

2 Answers2

3

RequireJS won't automatically check for the presence of index.js and load that as your module. You need to tell RequireJS that when you want to load someModule, it should load someModule/index. I'd set a map in my call to require.config:

require.config({
  [ ... ]
  map: {
    '*': {
        someModule: 'someModule/index',
    }
  },
});

You have to adjust the name you give there so that it is a path relative to your baseUrl. It's not clear from the information you give in your question what it should be.

(For the record, there's also a packages setting that you could probably tweak to do what you want but putting something packages says "this is a package", which is not what you appear to have here. So I would not use it for what you are trying to do.)

Louis
  • 146,715
  • 28
  • 274
  • 320
  • Perfect, Thanks! Is there any way to do this dynamically or does every package I use that has an index need to be defined here? – Devan Buggay Jan 23 '17 at 23:35
  • 2
    You need to do it for every module. There's no support to turn this on in some sort of dynamic way or use pattern matching. The `'*'` you can use in `map` is a really a hardcoded name that means "in all modules" and it is only significant as a key of `map` itself, and nowhere else. `map` would not understand things like `foo*`, nor could you do something like `map: { '*': { '*': '...'}}` The second `*` would be interpreted literally by RequireJS as "a module named `*`" and not as "all modules".. – Louis Jan 23 '17 at 23:40
  • This doesn't work for me, not sure why. Require ignores the map setting – Tyguy7 Jun 22 '17 at 23:55
  • I think if your index exports all features of the module/package, the `packages` config is what you want. For me, `map` doesn't work, because my `index.js` has local dependencies, which are then changed to `someModule/index/dep`, although they should remain `someModule/dep`. For me `packages:[{name: 'someModule', main: 'index'}]` works like a charm. (also works with e.g. `subdir/someModule`) – Neonit Mar 20 '18 at 10:30
1

I didn't like the configuration in map either. The most simple way I accomplished this was writing a plugin for require.

Let's name the plugin mod, where it is to be used as mod!module/someModule, you can also call it index as in index!module/someModule, whatever suits you best.

define(function(require, exports, module) {
   // loading module/someModule/index.js with `mod!`      
   var someModule = require('mod!module/someModule');

   // whatever this is about ..
   module.exports = { .. };
});

So lets assume you have paths set in require's configuration with some sort of project structure:

- app
  - modules
    - someModule/index.js        // the index we want to load
    - someModule/..
    - someModule/..
    - etc
  - plugins
    - mod.js                     // plugin to load a module with index.js

Requires config:

require.config({
   paths: {
      'module': 'app/modules',

      // the plugin we're going to use so 
      // require knows what mod! stands for
      'mod': 'app/plugins/mod.js'
   }
});

To read all the aspects of how to write a plugin, read the docs at requirejs.org. The simplest version would be to just rewrite the name of the requested "module" you are attempting to access and pass it back to load.

app/plugins/mod.js

(function() {
    define(function () {
        function parse(name, req) {
            return req.toUrl(name + '/index.js');
        }

        return {
            normalize: function(name, normalize) {
                return normalize(name);
            },
            load:function (name, req, load) {
                req([parse(name, req)], function(o) {
                    load(o);
                });
            }
        };
    });
})();

This is not production code, it's just a simple way to demonstrate that requires config wasn't meant to solve problems like this.

dbf
  • 3,278
  • 1
  • 24
  • 34