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

The amd files in the zip file is not working with requirejs #168

Closed
saadtazi opened this Issue Nov 22, 2012 · 13 comments

Comments

Projects
None yet
4 participants
@saadtazi
Contributor

saadtazi commented Nov 22, 2012

the zip that can be downloaded from the AMD section of http://canjs.us (https://github.com/downloads/bitovi/canjs/can.js.1.1.1.zip) contains amd/ files that do not work: a lot of files in the require() first array parameter contains '.js' which breaks the loading (generates 404 errors) with requirejs.
Example with amd/can/util/array/each.js in the zip (line 1) - notice the '.js' in 'can/util/can.js:

define(['can/util/can.js'], function (can) {

FYI: The 1.1.0 zip that I downloaded a couple of days ago was also working.

FYI: From http://requirejs.org/docs/api.html:

There may be times when you do want to reference a script directly and not conform to the "baseUrl + paths" rules for finding it. If a module ID has one of the following characterstics, the ID will not be passed through the "baseUrl + paths" configuration, and just be treated like a regular URL that is relative to the document:
Ends in ".js".
Starts with a "/".
Contains an URL protocol, like "http:" or "https:".

note: I originally said that rebuilding canjs amd with latestest changes fixes the issue. I just retested it with I fresh clone of donejs and it is actually not the case: I get the '.js' after building - same files that are downloadable.

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Nov 22, 2012

Contributor

So what I read from that documentation is that the standard configuration will work (I got it working with Require and the AMD builds at least) but as soon as you add paths or mappings (like map can to js/can) it will not run any filename that ends with .js through the path/mappings right?

That should be easy to fix (the previous AMD builder removed the .js parts) as long as we have a way to map libraries (can/util.js -> can/util/jquery).

Contributor

daffl commented Nov 22, 2012

So what I read from that documentation is that the standard configuration will work (I got it working with Require and the AMD builds at least) but as soon as you add paths or mappings (like map can to js/can) it will not run any filename that ends with .js through the path/mappings right?

That should be easy to fix (the previous AMD builder removed the .js parts) as long as we have a way to map libraries (can/util.js -> can/util/jquery).

@saadtazi

This comment has been minimized.

Show comment
Hide comment
@saadtazi

saadtazi Nov 22, 2012

Contributor

Even without mappings or paths (except a path for jquery), the only way to have it work is to have the can/ folder at the root level of the site. Using data-main attribute won't work, even if you have the can/ folder under the js folder:

<script data-main="js/main.js" type="text/javascript" src="lib/require.js"></script>

I get the following error:

"NetworkError: 404 File not found - http://127.0.0.1:8000/can/util.js"
"NetworkError: 404 File not found - http://127.0.0.1:8000/can/view/scanner.js"
"NetworkError: 404 File not found - http://127.0.0.1:8000/can/view/render.js"

It seems to work if I remove all the '.js' in the require() call, even with the data-main, which allows to organise js files.

Contributor

saadtazi commented Nov 22, 2012

Even without mappings or paths (except a path for jquery), the only way to have it work is to have the can/ folder at the root level of the site. Using data-main attribute won't work, even if you have the can/ folder under the js folder:

<script data-main="js/main.js" type="text/javascript" src="lib/require.js"></script>

I get the following error:

"NetworkError: 404 File not found - http://127.0.0.1:8000/can/util.js"
"NetworkError: 404 File not found - http://127.0.0.1:8000/can/view/scanner.js"
"NetworkError: 404 File not found - http://127.0.0.1:8000/can/view/render.js"

It seems to work if I remove all the '.js' in the require() call, even with the data-main, which allows to organise js files.

@rjgotten

This comment has been minimized.

Show comment
Hide comment
@rjgotten

rjgotten Nov 22, 2012

If you require a module through a URI that has a file extension attached, then said URI will be used untouched as the direct URL from which to retrieve the resource.

That means the URI:

  • will not be processed by the maps config,
  • will not be processed by the paths config,
  • will not be resolved against the current module URI, and
  • will not be resolved against the configuration base URL.

Basically; all URL resolution built into your AMD loader will be skipped.

As a rule of thumb, you should never specify the file extension as part of the module URI, unless you are hard-linking to a very particular file location, which is most often when you are loading plain (non-AMD) JS or non-JS resources. (In case of the latter you'd almost exclusively be using a loader plugin for that particular family of non-JS resource as well.)

rjgotten commented Nov 22, 2012

If you require a module through a URI that has a file extension attached, then said URI will be used untouched as the direct URL from which to retrieve the resource.

That means the URI:

  • will not be processed by the maps config,
  • will not be processed by the paths config,
  • will not be resolved against the current module URI, and
  • will not be resolved against the configuration base URL.

Basically; all URL resolution built into your AMD loader will be skipped.

As a rule of thumb, you should never specify the file extension as part of the module URI, unless you are hard-linking to a very particular file location, which is most often when you are loading plain (non-AMD) JS or non-JS resources. (In case of the latter you'd almost exclusively be using a loader plugin for that particular family of non-JS resource as well.)

@saadtazi

This comment has been minimized.

Show comment
Hide comment
@saadtazi

saadtazi Nov 23, 2012

Contributor

@rjgotten , I also think that the js files in amd/ should not specify the file extension as part of the module URI.

@daffl : to map util to a specific libray, what about using:

map : {
    '*' : {
          "can/util" : "can/util/zepto" // no .js
    }

I have to admit that I didn't test it, I will try tomorrow if I have time... or this wend-end.

Contributor

saadtazi commented Nov 23, 2012

@rjgotten , I also think that the js files in amd/ should not specify the file extension as part of the module URI.

@daffl : to map util to a specific libray, what about using:

map : {
    '*' : {
          "can/util" : "can/util/zepto" // no .js
    }

I have to admit that I didn't test it, I will try tomorrow if I have time... or this wend-end.

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Nov 23, 2012

Contributor

@saadtazi This won't work because mapping can/util to can/util/zepto will map any other module name like can/util/string to can/util/zepto/string which is not what we want.

We have a new AMD build ready that should solve the above issues. Hopefully it will be published with version 1.1.2 tomorrow.

Contributor

daffl commented Nov 23, 2012

@saadtazi This won't work because mapping can/util to can/util/zepto will map any other module name like can/util/string to can/util/zepto/string which is not what we want.

We have a new AMD build ready that should solve the above issues. Hopefully it will be published with version 1.1.2 tomorrow.

@rjgotten

This comment has been minimized.

Show comment
Hide comment
@rjgotten

rjgotten Nov 23, 2012

@daffl If you're worried about path remappings, then a not-so-easy but more bulletproof way out is to create a loader plugin that handles switching between the various selector libraries and to configure it using module config.

Given a simple loader plugin can/util/lib.js :

define([ "module" ], function( module ) {
  var lib = "./" + ( module.config().lib || "jquery" );

  return {
    load : function( name, require, load, config ) {
      require([ lib ], load );
    }
  }
});

and an application configuration:

require.config({
  config : {
    "can/util/lib" : { lib : "zepto" } // want zepto instead of jquery
  }
})

You could have can/util.js import a configured library through the plugin:

define([ "./lib!" ], function( lib ) {
});

This is similar to how the RequireJS optimizer dynamically loads dependencies for either the NodeJS or RhinoJS environment. (I'd also recommend using module config to decide on whether to inject the window.can global or not, if you aren't doing so already.)

Also note the use of relative paths; if you have all the CanJS components use a relative path, then you can easily move the entire library around your project structure.

rjgotten commented Nov 23, 2012

@daffl If you're worried about path remappings, then a not-so-easy but more bulletproof way out is to create a loader plugin that handles switching between the various selector libraries and to configure it using module config.

Given a simple loader plugin can/util/lib.js :

define([ "module" ], function( module ) {
  var lib = "./" + ( module.config().lib || "jquery" );

  return {
    load : function( name, require, load, config ) {
      require([ lib ], load );
    }
  }
});

and an application configuration:

require.config({
  config : {
    "can/util/lib" : { lib : "zepto" } // want zepto instead of jquery
  }
})

You could have can/util.js import a configured library through the plugin:

define([ "./lib!" ], function( lib ) {
});

This is similar to how the RequireJS optimizer dynamically loads dependencies for either the NodeJS or RhinoJS environment. (I'd also recommend using module config to decide on whether to inject the window.can global or not, if you aren't doing so already.)

Also note the use of relative paths; if you have all the CanJS components use a relative path, then you can easily move the entire library around your project structure.

@jeffrose

This comment has been minimized.

Show comment
Hide comment
@jeffrose

jeffrose Nov 26, 2012

I hate to be "that guy" but when will 1.1.2 be released?

jeffrose commented Nov 26, 2012

I hate to be "that guy" but when will 1.1.2 be released?

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Nov 26, 2012

Contributor

I uploaded a 1.1.2 preview with the new builds. Maybe you can try it out and let me know if it solves the problem. Instead of can/util.js it now loads the can/util/library module which loads jQuery by default. Everything else is now using actual module ids (without the .js extension) as well.

This build is being used in the CanJS + RequireJS TodoMVC example and seems to work fine (but it doesn't need any mappings, either).

Contributor

daffl commented Nov 26, 2012

I uploaded a 1.1.2 preview with the new builds. Maybe you can try it out and let me know if it solves the problem. Instead of can/util.js it now loads the can/util/library module which loads jQuery by default. Everything else is now using actual module ids (without the .js extension) as well.

This build is being used in the CanJS + RequireJS TodoMVC example and seems to work fine (but it doesn't need any mappings, either).

@jeffrose

This comment has been minimized.

Show comment
Hide comment
@jeffrose

jeffrose Nov 26, 2012

So you would only need a mapping if you wanted to use a library other than jQuery?

jeffrose commented Nov 26, 2012

So you would only need a mapping if you wanted to use a library other than jQuery?

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Nov 26, 2012

Contributor

Yes. For e.g. Mootools you would do

require.config({
  map : {
    '*' : {
          "can/util/library" : "can/util/mootools"
    }
  },
  paths: {    
    "mootools" : "path/to/mootools-amd.js"
  }
});
Contributor

daffl commented Nov 26, 2012

Yes. For e.g. Mootools you would do

require.config({
  map : {
    '*' : {
          "can/util/library" : "can/util/mootools"
    }
  },
  paths: {    
    "mootools" : "path/to/mootools-amd.js"
  }
});
@jeffrose

This comment has been minimized.

Show comment
Hide comment
@jeffrose

jeffrose Nov 26, 2012

I ended up doing this...

"paths": {
    "can": "can-1.1.2-pre",
    "can/util/library": "can-1.1.2-pre/util/jquery"
}

Mostly to cut out the library "middleman." I was actually fine with being required to map a library (e.g. can-library in 1.1.0) but having a default file is fine too.

I noticed that can/util has can/util/jquery as a dependency. I assume that should be can/util/library.

jeffrose commented Nov 26, 2012

I ended up doing this...

"paths": {
    "can": "can-1.1.2-pre",
    "can/util/library": "can-1.1.2-pre/util/jquery"
}

Mostly to cut out the library "middleman." I was actually fine with being required to map a library (e.g. can-library in 1.1.0) but having a default file is fine too.

I noticed that can/util has can/util/jquery as a dependency. I assume that should be can/util/library.

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Nov 26, 2012

Contributor

We want to be able to use AMD + jQuery without having to map anything CanJS specific. can/util is not really used anymore. I will make sure that it just maps to to can/util/library as you suggested. If everything else works I will get 1.1.2 out later today.

Contributor

daffl commented Nov 26, 2012

We want to be able to use AMD + jQuery without having to map anything CanJS specific. can/util is not really used anymore. I will make sure that it just maps to to can/util/library as you suggested. If everything else works I will get 1.1.2 out later today.

@ghost ghost assigned daffl Nov 27, 2012

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Nov 28, 2012

Contributor

1.1.2 is out and it seems to solve all the AMD problems mentioned above. Closing.

Contributor

daffl commented Nov 28, 2012

1.1.2 is out and it seems to solve all the AMD problems mentioned above. Closing.

@daffl daffl closed this Nov 28, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment