Frage

I am trying to use RequireJS in node, and found difficulties with path issues.

Here is a simple foo method that returns "foo"

$ cat src/foo.js 

define([], function() {

    var foo = function() {
        return "foo";
    };

    return { foo:foo};
});

Here is bar that requires foo, but it works only when specifying relative path. Is that how it's supposed to be?

$ cat src/bar.js
define(['./foo.js'], function(foo) {

    var bar = function() {
        return foo.foo().replace("foo","bar");
    };

    return { bar : bar };
});

Things get much trickier in the mocha test:

  1. Loading foo and bar requires __dirname workarounds.
  2. The async loading of bar fails (see test 3 and 4).
  3. Importing Squire needs exact path, since it is installed using npm install, but does not conform to the standard node require syntax and does not include the amdefine workaround:

Here is the test code:

$ cat test/footests.js 
var requirejs = require('requirejs');
var chai = requirejs("chai");
var should = chai.should();
var Squire = requirejs(__dirname + "/../node_modules/squirejs/src/Squire.js");

describe('when calling foo.foo()', function () {
   it('should return "foo"', function() {
        var foo = requirejs(__dirname + "/../src/foo.js");
        foo.foo().should.equal("foo");
    });
});

describe('when calling bar.bar()', function () {
    var bar = requirejs(__dirname + "/../src/bar.js");
    it('should return "bar"', function() {
        bar.bar().should.equal("bar");
    });
});

describe('when calling bar.bar() with async requirejs', function () {
    it('should return "bar"', function(done) {
        requirejs(__dirname + "/../src/bar.js", function(bar) {
            bar.bar().should.equal("bar");
            done();
        })
    });
});
describe('when mocking foo.foo() and calling bar.bar()', function () {
    it('should return "barbar"', function(done) {
        var injector = new Squire();
        var fooMock = {
            foo : function() {
                return "foofoo"; /* instead of just foo */
            }
        };
        injector
          .mock('./foo.js', fooMock)
          .require(__dirname + "/../src/bar.js", function(bar) {
              bar.bar().should.equal("barbar");
              done();
          });
    });
});

I've setup a reproduction on github https://github.com/itaifrenkel/node-requirejs-example

War es hilfreich?

Lösung

There are multiple issues in your code:

  1. Don't put .js at the end of module names. Adding .js tells RequireJS to bypass the normal module name resolution. (There are some cases where you want the extension but these should be cases where you can say why you need it.)

  2. RequireJS in Node can take a configuration, just like when you use it in a browser. This eliminates the need to duplicate paths all over the place.

  3. RequireJS can load packages with the packages setting.

  4. Don't load Node modules with RequireJS when there's no need for it. (For instance, chai does not need to be loaded with RequireJS.)

If I modify bar.js to drop the .js extension from its lone dependency and use the following test file, it works:

var requirejs = require('requirejs');
requirejs.config({
    baseUrl: __dirname + "/../src",
    packages: [
        {
            name: "squirejs",
            location: "../node_modules/squirejs",
            main: "src/Squire"
        }
    ]
});
var chai = require("chai");
var should = chai.should();
var Squire = requirejs("squirejs");

describe('when calling foo.foo()', function () {
   it('should return "foo"', function() {
        var foo = requirejs("foo");
        foo.foo().should.equal("foo");
    });
});

describe('when calling bar.bar()', function () {
    var bar = requirejs("bar");
    it('should return "bar"', function() {
        bar.bar().should.equal("bar");
    });
});

describe('when calling bar.bar() with async requirejs', function () {
    it('should return "bar"', function(done) {
        requirejs(["bar"], function(bar) {
            bar.bar().should.equal("bar");
            done();
        });
    });
});
describe('when mocking foo.foo() and calling bar.bar()', function () {
    it('should return "barbar"', function(done) {
        var injector = new Squire();
        var fooMock = {
            foo : function() {
                return "foofoo"; /* instead of just foo */
            }
        };
        injector
          .mock('./foo', fooMock)
          .require(["bar"], function(bar) {
              bar.bar().should.equal("barfoo");
              done();
          });
    });
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top