require.js allows to smartly redefine the "include path" so that you can decide to install your dependancies into arbitrary sub-directories, transparently for them.
Well, this is true for the recursive require() these might do, but unfortunately it doesn't seem to work for the jquery load/get they might do: these still refere to html path, so that datas cannot be moved together with their lib.js.
how to make jquery load/get refer to this current require path ?
or am I missusing require.js features ?
thanks !
You can use toUrl for this. (Documented: go here in the documentation and search for toUrl.)
You need to have require as a dependency of your module (define(["require", ...], function (require, ...) {...) and then you call require.toUrl(path) where path is a path relative to your module. This call will return a path which is the same as if the path argument were a module's path defined in your RequireJS configuration. In other words, it is a path which will be relative if your baseUrl in your configuration was relative, or absolute if baseUrl is absolute. At any rate, you should just be able to feed it to $().load or $.get.
Related
I am writing a Pug dependency loader. Basically it will just output an identical Pug file, except that require() calls will be replaced with a path to the file they are requiring. Obviously, therefore, I need to take that path and hand it off to the Webpack loader chain so that it will be handled in whatever way is appropriate, e.g. by using file-loader to copy an image file to its appropriate location.
Everything's working except for this part. I can't figure out how to pass the path to Webpack to be loaded. To be clear, I want the same sort of thing to happen as when you require() a file in your Webpack entry file - Webpack should take the path, run it through the list of possible loaders, and handle it appropriately.
I have tried just using a require() call, I've tried this.resolve() and this.loadModule() but none have worked. Since this.resolve() accepts a context as its first argument, I have carefully given it the appropriate context of my /src folder. The image is at /src/images/image.jpeg, and yet it actually gives an error that it cannot resolve that path, even though it is correct, so I'm not sure what I'm doing wrong or how to make this work.
The link https://github.com/jhades/angularjs-gulp-example/blob/master/gulpfile.js has the gulp build-js task definition using browserify paths. I don't understand the need for it... wasn't it possible just to specify the entries as entries: './js/**/*.js', and this would have caused it to search all the sub-directories as well... instead of explicitly specifying paths: ['./js/controllers', './js/services', './js/directives'], which are all sub-directories of the same parent?
Any hints appreciated.
The author is using the paths configuration to enable non-relative require calls like these:
require('todoCtrl');
require('todoStorage');
require('todoFocus');
require('todoEscape');
require('footer');
Browserify emulates Node's module resolution mechanism (which is explained here) and when Node resolves a non-relative require, it looks in node_modules. The paths option gives Browserify a list of paths that are not in node_modules that it should check (before checking node_modules) when attempting to resolve non-relative require calls.
If all of your require calls for modules in your own project use relative paths (e.g. require('./js/controllers/todoCtrl')), you won't need the paths configuration option.
Well, one simple answer seems to be the fact that **/* is not recognised by browserify! You would have to require("glob") to do that... but it's probably simpler just to use paths to specify the extra folders.
I want to be able to know what path node's require will resolve to without running a require.
For example
var myVar = require('./some_module')
Internally node.js will look through its PATH, figure out whether it's a directory, a js file, a json file, etc., and then load the file.
Is there a way to just as for the full resolved path without actually loading the module?
The output I'm looking for would be something like
/Users/myUser/awesomeProject/some_module.js
The important part being the .js extension, since node would have had to fully resolve the path.
note: require('path').resolve ... does not solve this issue. What if some_module is actually a directory with a package.json inside of it, etc.
Turns out node has a way to do this! It's just not easy to find in their documentation. Calling
require.resolve('./some_module')
gives me exactly what I'm looking for
Here's the only reference I've found in the docs: https://nodejs.org/api/modules.html#modules_all_together
Here there is a paths alias "jquery" in require.js config
Require.JS is triggering require callback for "jquery" but it doesn't trigger the require callback if absolute path is specified for jquery module.
<script type="text/javascript">
var require = {
baseUrl : "../../",
paths : {
'jquery' : '/js/jquery-1.8.3',
},
};
</script>
<script type='text/javascript' src='/js/require.js'></script>
<script type="text/javascript">
require(['jquery'],function(obj) {
console.info("jquery loaded","alias");
});
require(['jquery'],function(obj) {
console.info("jquery loaded","alias");
});
require(['/js/jquery-1.8.3.js'],function(obj) {
console.info("jquery loaded","absolute path");
});
</script>
I expected console.info from the last require statement to be executed, but it doesn't trigger. Looks like if you require a path alias and then require the absolute path,it's not triggering the callback.
Is this a bug in Require.JS or any alternate ways to get callback triggered with both path alias and absolute path?
Correct. Trying to load the same module under two different names does not work. There's good evidence this is by design.
RequireJS treats modules as singletons. (The scope of the "singelton-ness" is a RequireJS context. So the same module could be instantiated once for a context and a second time for a different context but it will never be instantiated twice for the same context.) When RequireJS loads a module, the module acquires a name. If the define call has a string as the first argument, the name is this string. Otherwise, if there was no map affecting the loading of the module, the name will be the string that appeared in require or define call that the listed the module as a dependency. So, using your configuration in the question, if you do require(['jquery'], ... or have a module foo that is defined as define(['jquery'], ... then the name that will be given to the module found at js/jquery-1.8.3 is jquery. Then there is the fact that inside a module, you get get the module name by doing something like this:
define(['module'], function (module) {
console.log("my module name: " + module.id);
});
Ok, so what happens if your module is required twice with two different module names? Remember that modules are singletons so RequireJS won't execute the define twice. Which id should the module get?
In practice, it is almost always the case that when the same module code is being loaded under two different names, it is an programming mistake rather than something the developers really wanted to do. I've never run into a codebase where RequireJS was used where it would have been valid to load jQuery both as jquery and using a path with the version number. The latter case would indeed be an error. So rather than use some sort of default behavior that will probably lead to surprises down the road, RequireJS breaks right away when you try to load the same module under two different names. This is the safe thing to do.
Now, if you really really must be able to load the same module with two names, then you can do it but you must be explicit about what you want: you can use map. This will establish an unambiguous relation between the module names you want to use. What a map does is basically saying "when code in module X requires module Y load module Z instead." So in your case:
map: {
'*':
'/js/jquery-1.8.3': 'jquery'
}
}
This says "when code in any module (*) requires /js/jquery-1.8.3 load jquery instead". In case you wonder, this won't result in a circular dependency. RequireJS will see /js/jquery-1.8.3 passed to require or define, will then inspect the map and convert it to jquery, will then find jquery in paths and convert it to /js/jquery-1.8.3 and then add the .js extension and fetch the module. After it has gone through paths it does not go back to map, because the result it gets from paths is a path, not a module name (and map only transforms module names).
Note that with the map above, there is only one module loaded, which is named jquery. If module.id were used in it, it would always have the value "jquery" and could not have any other value.
Important side note: you should not put the .js in the require call, otherwise it won't work: require(['/js/jquery-1.8.3'], ....
I have the baseUrl in a RequireJs based application set to /angular. Sometimes I'd like to set the path relative to the base, other times I'd like to set it relative to the current directory.
I'm very new to RequireJs and very confused.
This is what I have now:
require([
'require',
'angular',
'module/draft/draftDisplay'// module that I want relative to baseUrl
], function(requireLocal, angular) {
requireLocal('./autoSave'); // Modules that I want relative to current url
requireLocal('./module');
Which creates this error: Error: Module name "autoSave" has not been loaded yet for context: _
As I said before, I can't get a good handle on how RequireJs works. Some things I don't understand are:
1) When does RequireJs use the baseUrl and when does it use the current directory
2) What's the difference between a module ID and its path?
3) Does the way previous modules are specified in the require([...],.. array affect how subsequent ones are resolved (which seemed to be the case when I tinkered)
If you could include those things in your answer, that would be very helpful.
1) When does RequireJs use the baseUrl and when does it use the current directory
Always baseUrl, except when the module name is prefixed by ./ or ../, in which case it uses the directory of the module that requires the other.
2) What's the difference between a module ID and its path?
The path includes the baseUrl. E.g. could be something like scripts/vendor/angular/angular.js. The module id does not include the baseUrl or the suffix, e.g. for baseUrl: 'scripts', the module id above would be vendor/angular/angular.
3) Does the way previous modules are specified in the require([...],.. array affect how subsequent ones are resolved (which seemed to be the case when I tinkered)
No.
Your error is caused from using the synchronous version of require for modules that are not loaded. Use the asynchronous version instead; something like:
requireLocal(['./autoSave', './module'], function(autosave, module) {
// here autosave and module are loaded
});
// BEWARE: Here neither autosave nor module are loaded
But are you sure you want the inner require? From the information you provide, pulling the requirements in the outer require would probably suffice, i.e.
require(['require','angular','module/draft/draftDisplay','./autoSave','./module'],...)
Also, the import called 'module' has special meaning in require; it contains information about the current module; If you are literally using './module' it will be quite different than 'module' (the first looks for a module.js file in the same directory as this file, the second provides information about this module).