requirejs / r.js

Runs RequireJS in Node and Rhino, and used to run the RequireJS optimizer
Other
2.57k stars 673 forks source link

Incorrect Module ID Created for define() when Built #635

Closed ryanfitzer closed 10 years ago

ryanfitzer commented 10 years ago

I've tracked it down to the normalize method in RequireJS where baseName and name are getting concatenated together (line 299). Unfortunately, I have to use a difficult directory structure. Changing it is not an option.

Here's my setup:

Directory Structure

└── clientLibs
    └── common
        └── js
            └── config
                └── require-config.js
    └── template-one
        └── js
            └── index.js

Here's what the modules array looks like for the build options:

modules: [

    {
        name: '../../template-one/js/index'
    }
]

build.txt:

common/js/../../template-one/js/index.js
----------------
common/js/../../template-one/js/../../common/js/config/require-config.js
common/js/../../template-one/js/index.js

require-config.js:

require.config({
  // Options
});

index.js (pre-build):

require( [ '../../common/js/config/require-config' ], function() {
    // Do something
});

index.js (post-build):

require.config({
  // Options
});
define("../../template-one/js/../../common/js/config/require-config", function(){});

require( [ '../../common/js/config/require-config' ], function() {
    // Do something
});
define("../../template-one/js/index", function(){});

As you can see, the define ID being created is ../../template-one/js/../../common/js/config/require-config, but what's being require'd is ../../template-one/js/index.

I'm using the map option in my "require-config.js" as a quick fix, but that's not sustainable in the long term. Any ideas on how I can get the correct module ID created?

jrburke commented 10 years ago

If a module ID goes outside the module ID namespace (it ends up with a '..' in front of its final, resolved module name) there will be issues.

Best to set a paths config instead and keep the module IDs in the module ID namespace, like paths: { 'template-one': '../../template-one/' } and same for 'common' if you need to use '../../common' to refer to it.

That should fix the issue.

ryanfitzer commented 10 years ago

Thanks @jrburke. Question:

If a module ID goes outside the module ID namespace

Is the directory set in baseUrl considered the "module ID namespace". This is the first I've heard it described this way.

jrburke commented 10 years ago

Yes, the baseUrl usually sets the root of the module ID space, with paths configs setting module ID prefixes (which are rooted to the root of the module ID space) to different file paths prefixes.

I definitely should do a better job of explaining this, the docs are lacking on this for sure. That is partly because when I started, I tried to be more lax and allow someone to just take their script src URLs and drop them into a require() call, so the module ID space was a bit murky, and this issue ticket is a reflection of that. In retrospect I should have made a clean break with URLs and be stricter on maintaining the module ID space correctly. Something I am looking to do for any 3.0 effort.