Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relative module path resolution fails after loading from absolute path #230

Closed
elima opened this issue Apr 3, 2012 · 8 comments
Closed

Comments

@elima
Copy link

elima commented Apr 3, 2012

When I 'require' a remote module using an absolute url (http://) path, and that module requires other modules relative to it, the resolved paths for these modules are also absolute but lack the ".js" extension thus they are not found.

Example:

require (["http://other.domain/remoteModule.js"], function (RemoteModule) {
   ...
});

And inside RemoteModule:

define (["./otherModule"], function (OtherModule) {
   ...
});

Require.js will load RemoteModule fine, but then will try to load OtherModule from the url http://other.domain/otherModule (without the extension) and fails with not-found error.

My use case is simply loading a remote module that has relative dependencies. What would be the correct way to do this?

@elima
Copy link
Author

elima commented Apr 3, 2012

This is my (certainly wrong) workaround in nameToUrl() function:

diff --git a/require.js b/require.js
index 0ca0c1b..a307cd6 100644
--- a/require.js
+++ b/require.js
@@ -1475,6 +1475,9 @@ var requirejs, require, define;
                 var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
                     config = context.config;

+                if (relModuleMap && req.jsExtRegExp.test(relModuleMap.originalName))
+                    moduleName += ".js";
+
                 //Normalize module name if have a base relative module name to work from.
                 moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);

@jrburke
Copy link
Member

jrburke commented Apr 21, 2012

Sorry, I meant to comment sooner:

I expect that if you create a paths entry for it in the config call it should work out:

requirejs.config({
  paths: {
    'remoteModule': 'http://other.domain/remoteModule'
  }
});

//Then later...
require (['remoteModule'], function (RemoteModule) {

});

The full URL support in requirejs is really just to help easily incorporate non-module scripts into a project. However, for modules, it is best to use module naming with path entries. This also opens up the possibility of mapping that dependency to a local file in a build.

@jrburke jrburke closed this as completed Apr 21, 2012
@jrburke
Copy link
Member

jrburke commented Apr 22, 2012

Ah, one adjustment to the above: module IDs are resolved relative to other modules IDs, not paths. So the above config and module ID use should really be:

requirejs.config({
  paths: {
    'remote': 'http://other.domain'
  }
});

//Then later...
require (['remote/remoteModule'], function (RemoteModule) {

});

Note the usage of a prefix "remote" for the ID. So if remoteModule.js has a './something' module ID reference, it is resolved to 'remote/something' which then gets that above path applied to it.

@itay
Copy link

itay commented Sep 27, 2013

@jrburke I actually just ran into this issue as well, and I cannot put in a "path" entry.

In my case, I load A like so: require(["/path/to/modules/a.js"], ...)

In a.js, I have this define(["../othermodule/otherfile"]).

The above fails because, because now require tries to load the absolute path /path/to/modules/othermodule/otherfile rather than /path/to/modules/othermodule/otherfile.js, which obviously doesn't work.

I also can't change a.js to have otherfile.js because then it doesn't work when I have relative includes. It seems I have an either or situation.

Is there any way to fix it or work around it? Using a 'path' definition isn't really an option in our case.

@neonstalwart
Copy link
Contributor

@itay to use relative ids in a module, requirejs has to understand the id of the module that's using relative ids (think of module ids as a separate namespace to URLs). if your A module had an id then you could load it using require(["id/of/a"], ...) rather than require(["/path/to/modules/a.js"], ...)

the paths config is one way to teach requirejs the id of your module. without finding some way for requirejs to understand the id of your module, relative ids won't work.

@itay
Copy link

itay commented Sep 27, 2013

@neonstalwart I'm not 100% sure I follow. Let me give a more formal sample:

Directory:

    /apps
        /app1
            /static
                module1/
                    module1.js
                module2/
                    module2.js
        /app2
    /static
        require.js

module1.js:

define(['../module2/module2'], function(module2) {
    // ...
});

module2.js:

define([], function() {
    console.log("HELLO WORLD");
    return "BOO";
});

I guess my confusion stems from the fact that if I do this:

doesntwork.html:

<script>
require.config({
    baseUrl: '/static/js'
});

require(['/static/apps/app1/module1/module1.js'], function(module1) {
    // ... 
});
</script>

It doesn't work, because what require.js ends up doing is trying to loading /static/apps/app1/module2/module2, instead of /static/apps/app1/module2/module2.js - everything is correct, except the lack of the .js. So it is calculating the paths correctly, etc, which is all great. It just isn't adding the extension.

I don't see why it changes whether the extension is added or not based on how the module was originally required. Because if I do this instead:

index.html:

<script>
require.config({
    baseUrl: '/static/js',
    paths: {
        app_root: '../static/apps'
    }
});

require(['app_root/app1/module1/module1.js'], function(module1) {
    // ... 
});
</script>

It does work. Basically, the only thing that changed is that if I do a require with an absolute URL, then no .js is added, but if I do it with a relative URL, one is added.

Does that make more sense?

The reason I can't add a paths config is a fairly esoteric one and specific to our particular deployment, but take my word that it is not really an option for me :)

@gravitypersists
Copy link

Can this issue please be re-opened? Adding to your paths is not an option for me either-

@fdecampredon
Copy link

we use requirejs to provide a kind of 'plugin' system, and it seriously makes everything complex, @jrburke could we hope that you reconsider ? adding a 'path' is not an option for us neither.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants