7

I'm trying to load a library that compiles to Webpack in a require.js project. While the library exposes an object, it returns null when required from the require.js project :

define(function(require, exports, module) {
  [...]
  require("./ext/mylib.core.js"); // -> null
})

Is there any flags that I can use in Webpack to enable AMD compliance ? There are some references to AMD in the generated library but as it is it does not seem to do anything.

fredericlb
  • 191
  • 7

2 Answers2

5

The solution was in Webpack documentation : there is an outputLibrary flag that can be set to "amd" or "umd" and in that case webpack produces amd compliant modules.

fredericlb
  • 191
  • 7
  • Nevermind, [I found it in the docs](http://webpack.github.io/docs/configuration.html#output-library) – mfeineis Oct 16 '15 at 07:38
  • I could not get this to work for me. I was hoping I should use a webpack library along side and separate from requirejs. – Chris Aug 26 '16 at 12:16
3

EDIT 3:/EDIT: 4 Webpack is not cooperating it may seem, so another possibility would be to expose the module with the shim config option:

require.config({
    paths: {
        // Tell require where to find the webpack thingy
        yourModule: 'path/to/the/webpack/asset'
    },
    shim: {
        // This lets require ignore that there is no define
        // call but will instead use the specified global
        // as the module export
        yourModule: {
            exports: 'theGlobalThatIsPutInPlaceByWebpack'
        }
    }
});

This obviously only works in the case that the webpack stuff is putting something in the global scope. Hope this helps!

EDIT 2: So I got the question wrong as pointed out in the comments. I didn't find any built-in functionality to produce AMD modules from webpack - the end result seems to be a static asset js file. You could wrap the result in a

define(function () {
    return /* the object that webpack produces */;
});

block, maybe with the help of some after-build event (e.g. using this after build plugin for webpack). Then you should be able to require the module with an AMD loader.

Original Answer:

require.js loads it's dependencies asynchronously, you have to declare them explicitly when you're not using the r.js optimizer or the like. So if the module exposes an AMD definition it should work like this:

// It works the way you did it ...
define(['path/to/your/module'], function (require, exports, module) {
    require('path/to/your/module'); // -> { ... }
});

// ... but I personally prefer this explicit syntax + it is
// friendlier to a code minifier
define(['path/to/your/module'], function (yourModule) {
    console.log(yourModule); // { ... }
});

Maybe you have to configure your require instance, there are docs for that.

EDIT1: as pointed out the way the module is being accessed is not wrong but the dependencies were missing, so I added code that is closer to the original question.

mfeineis
  • 2,607
  • 19
  • 22
  • Using `require("...")` like the OP does is generally correct. If there is a problem in the OP's case it is not because of the use of `require('...")` and changing it to what you suggest will change nothing (because RequireJS does exactly what you suggest behind the scenes). – Louis Oct 15 '15 at 13:18
  • True, it's not the usage of `require` but the `define` call, I'll make an edit for to highlight this fact, thx! – mfeineis Oct 15 '15 at 13:24
  • You did not understand what I meant. Read [this answer](http://stackoverflow.com/a/21023168/1906307) for a detailed explanation. What you are suggesting won't make a difference because the first snippet you show is *already* what RequireJS does (read the answer I link to all the way to the end), and you yourself admit that the first snippet is functionally equivalent to the second. – Louis Oct 15 '15 at 13:56
  • I see, I forgot about that string parsing thing for a moment... and it seems I got the question wrong. Its not the AMD but rather whether webpack can produce AMD. That'll be another edit :-). By the way: it doesn't do the exact thing, as I recall the function code will only be scanned iff there are no dependencies present, so for this specific module it will work, adding more will break, so leaving them out is probably safer in the future. – mfeineis Oct 15 '15 at 14:14
  • "I recall the function code will only be scanned iff there are no dependencies present" If you mean no dependencies on the `define` call, then yes, sure. Just don't mix the two styles in the same module. Most of my modules are written in the CommonJS style, no problem there. – Louis Oct 15 '15 at 14:16
  • Yepp, my modules are all in the AMD style, so I did mix that up indeed – mfeineis Oct 15 '15 at 14:20
  • I tried adding a wrapper for AMD support in Webpack generated files but it is not that easy (Webpack does not expose easily the "return" value of the compiled file). I think this could be done but with too much hacky edits and it would be quite difficult to run in a script. – fredericlb Oct 15 '15 at 20:42
  • I've thought of another way, maybe you can use the *shim* functionality, see my edit – mfeineis Oct 16 '15 at 07:28
  • The correct shim syntax seems to be `shim: {yourModule: {exports: 'theGlobalThatIsPutInPlaceByWebpack'}}` – akaihola Jul 22 '18 at 08:50
  • @akaihola thanks for catching that, I'll update the post – mfeineis Jul 25 '18 at 11:35