Related paths for dependencies in RequireJS define - javascript

In a requirejs module, i want to load some related files as dependencies. That files are in the same folder as module with define(). The module and related files maybe move to another location.
How can i set define's dependencies by related paths?
movableModule.js now:
define('movableModule', [
"changable/path/to/my/modules/relatedFile1",
"changable/path/to/my/modules/relatedFile2"
], function(){
console.log("movableModule loaded");
});
movableModule.js i want to be like this:
define('movableModule', [
"./relatedFile1",
"./relatedFile2"
], function(){
console.log("movableModule loaded relatively!");
});
As i know calling require.config and using baseUrl will change all routes in all modules, yes? and if no, i don't know how to use it in this case.

You should configure RequireJS to define your different paths.
Then you could request those module, just by their name :
require.config({
baseUrl: "/",
paths: {
"relatedFile1": "changable/path/to/my/modules/relatedFile1"
}
});
Then you'll be able to do :
define('movableModule', [
"relatedFile1"
], function(){
console.log("movableModule loaded");
});
Also, as mentionned in comments, you can define a partial path, and use it later for your incoming modules :
require.config({
baseUrl: "/",
paths: {
"modulePath": "changable/path/to/my/modules/"
}
});
And require your modules like that :
define('movableModule', [
"modulePath/module1",
"modulePath/module2"
], function(){
console.log("movableModule loaded");
});
Comment from the developer.

Related

Require JS files from bower_components by saying "require('library')" possible?

I'm new to RequireJS and it seems it might not actually be possible but I'll still go ahead and ask away in case I'm missing something.
In the docs it says..
This setup assumes you keep all your JavaScript files in a "scripts" directory in your project.
project-directory/
project.html
scripts/
main.js
helper/
util.js
But what if I have to require files from my bower installed files in bower_components:
project-directory/
bower_components/
jquery-mousewheel
jquery.mousewheel.js
lodash
dist
lodash.js
As you see, not all libraries have the same directory hierarchy and naming convention.
So I was wondering is there a simple way to require these bower libraries without actually knowing where their main files are, maybe by simply saying
require('jquery-mousewheel');
require('loadash');
?
setup your requirejs config to use paths
requirejs.config({
// ... config ...
paths: {
jquery-mousewheel: 'bower_components/jquery-mousewheel/jquery.mousewheel',
loadash: 'bower_components/lodash/dist/lodash'
}
// ... config ...
});
documentation for reference
I think this is a better solution...
requirejs.config({
baseUrl: 'bower_components/',
paths: { // path to your app
app: '../'
}
});
requirejs( [
'imagesloaded/imagesloaded',
'app/my-component.js'
], function( imagesLoaded, myComp ) {
imagesLoaded( '#container', function() { ... });
});

Require JS baseUrl conflict

I have two Javascript file loading from the same domain. Each JS performing different function and for that, I have used requirejs module loader.
My problem is, I have used require.config call under both js and baseUrl is different for both configuration.
JS1
require.config({
baseUrl : server + "js/", // server is 192.168.1.10:3000/
paths :
{
jquery : "jquery",
moment : "moment.min"
},
waitSeconds: 20
});
require(["jquery","moment"], function(jQuery,moment)
{
jQuery.noConflict();
window.moment = moment;
jQuery(function($)
{
window.$191 = $;
callback($191);
});
});
JS2
require.config({
baseUrl: "http://192.168.1.9:6060/App/resources",
paths:
{
moment: "js/moment.min",
ejs : "js/ejs"
}
});
require(["moment","ejs"],function()
{
callback("OK");
});
I am loading JS1 first followed by JS2, but when I am loading JS2 its baseUrl change by 1st one i.e. from JS1 (server+"js/") !! Which is totally wrong. Can some one point me out here, if something I have done wrong.
Nikos Paraskevopoulos has the right idea for one way (multiversion) to approach this, but I think there are two ways.
1. Using multiversion
Passing two configs to require.config() will return to you two unique require functions.
// It is important to give the config objects a "context" name.
// This is what keeps them unique.
var r1 = require.config({
context: "r1",
baseUrl: "//rawgithub.com/requirejs/text/2.0.10/"
});
var r2 = require.config({
context: "r2",
baseUrl: "//cdnjs.cloudflare.com/ajax/libs/require-text/2.0.10/"
});
In addition, even if you used the same baseUrl in each config in the sample above, each text module would be a unique instance because of the nature of multiversion support.
These can be used to load modules from different URLs. In the example below, text1 and text2 are different module instances, even though they are essentially the same file.
r1(["require", "text"], function(r, text1) {
// ...
});
r2(["require", "text"], function(r, text2) {
// ...
});
The "require" module is required as a dependency if you use the var myModule = require("..."); syntax within the module body.
If all your dependencies are declared in the dependency array then you do not need this.
(There is a simple example of this at this jsfiddle)
But back to your example, you can assign local require functions to each file, and load modules via that local require function.
JS1
(function () {
var r = require.config({
context: "JS1",
baseUrl: server + "js/", // server is 192.168.1.10:3000/
paths: {
jquery: "jquery",
moment: "moment.min"
},
waitSeconds: 20
});
r(["jquery", "moment"], function (jQuery, moment) {
jQuery.noConflict();
window.moment = moment;
jQuery(function ($) {
window.$191 = $;
callback($191);
});
});
}());
JS2
(function () {
var r = require.config({
context: "JS2",
baseUrl: "http://192.168.1.9:6060/App/resources/",
paths: {
moment: "js/moment.min",
ejs: "js/ejs"
}
});
r(["moment", "ejs"], function () {
callback("OK");
});
}());
Aside
It's unusual for modules to not start with a call to the define() function, however. Usually, config and the modules are in separate files. So you might have:
JS1-config.js and JS1.js
JS2-config.js and JS2.js
And JS1.js and JS2.js would be of the form:
define(["array", "of", "dependencies"], function(array_, of_, dependencies_) {
});
2. Using a consolidated require config
A cohesive application is probably better served with a single module loader configuration file. You have visibility on all the required modules, and it'll probably play better with the r.js optimiser, should you want to use that.
As such, I would recommend consolidating your configs into a single config for your application. This way you don't mix the module loader config with the code that actually uses the modules.
If you can't modify some of the code, then this could be tricky to do though.
E.g.:
var baseUrl1 = server + "js/";
var baseUrl2 = "http://192.168.1.9:6060/App/resources/";
require.config({
paths: {
jquery: baseUrl1 + "jquery",
moment: baseUrl1 + "moment.min",
//moment: baseUrl2 + "js/moment.min",
ejs: baseUrl2 + "js/ejs"
},
waitSeconds: 20
});
This assumes that both JS files can use the same "moment" module.

module config for path and shim

I'm building an AMD module which uses multiple libraries with globals from a subfolder. Too reduce code and prevent globals leaking I want to use a config, but it seems the require config is only usable in the global context (how ironic)?!
What I want to do inside my module is basically this:
define(['require'], function(require) {
require.config({
baseUrl: 'sub/directory/',
paths: {
libfoo: 'libfoo23.min',
},
shim: {
libfoo: {
exports: 'Foo'
}
});
require(['libfoo'], function(Foo) {});
});
No, you can't do that.
And there is a good reason for it: If the module loading configuration is defined inside a module that requires the configuration to be loaded, who comes first? It's a chicken and egg problem.
RequireJS tries to minimize global pollution; it succeeds in that by introducing just 2 globals, required for bootstrapping (require() and define()).
I usually do it this way.
config.js
require.config({
baseUrl: 'sub/directory/',
paths: {
libfoo: 'libfoo23.min',
},
shim: {
libfoo: {
exports: 'Foo'
}
});
bootstrap.js
define([ 'config' ], function() {
require([ 'main' ]);
});
And in the HTML, I bootstrap this way:
<script data-main="/public/app/bootstrap" src="~/public/vendor/requirejs/require.js"></script>
Everything else (the app) start in main.js

RequireJS not honoring relative paths when not loaded at "mysite.com/"

I'm having some trouble with requirejs and relative paths.
This is in my HTML file:
<script data-main="/app/main.js" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.1/require.js"></script>
My config is set up as follows:
requirejs.config({
baseUrl: '/vendor',
paths: {
// APP FILES
'app-base' : '../app',
'app-config' : '../config',
models : '../models', // where the models and collections are
templates : '../templates',
views : '../views',
lib : '../lib',
tasks : '../tasks',
router : '../app/router',
// VENDOR FILES
marionette : 'backbone.marionette',
},
deps: ['router'],
shim: {...}
});
When my app loads from the url "localhost:3000/" or "localhost:3000/applications" all of these paths resolve correctly. But when it's loaded from something like "localhost:3000/applications/app1", the paths resolve incorrectly.
The paths looks like this, respectively.
Correct:
"/models/test-model.js"
Incorrect:
"/applications/models/test-model.js"
I'm loading my modules using CJS as follows:
define( function( require ) {
var TestModel = require('models/test-model.js');
});
When I change the above to this --> var TestModel = require('/models/test-model.js');, it works. But this defeats the purpose of using relative paths.
Would love it if someone could help me out. I'm super confused.
When requiring a module, be sure to leave off the .js extension unless you are specifying a complete path.

Relative paths with RequireJS modules/packages

I'm fairly new to RequireJS and I've run into a bit of a problem. I've written a little framework built on Backbone using RequireJS and I want it to be re-usable in different projects. So, with some searching I learned that require allows packages. This seemed like what I was looking for. I have a main.js file to launch my app that essentially looks like this:
require.config({
packages: ['framework']
});
require(['framework'], function(framework) {
framework.createDash();
});
Then in the same directory as my main.js I have another directory called "framework" which contains another main.js which looks like this:
define(function(require, exports, module) {
exports.createDash = function(dash, element) {
require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) {
return new DashView({
model: new DashModel(dash),
el: element ? element : window
});
});
};
});
In searching I found this page which indicates that the 'require' argument should be scoped to the submodule. However, when I try to require things they are still relative to my original main.js. I've tried a number of things and searched for hours to no avail. Is there any way I can have my require/define calls within my package included relative to the main.js in it's root?
You need to define your submodule as package in the require configuration:
require.config({
packages: [
{ name: 'packagename',
location: 'path/to/your/package/root', // default 'packagename'
main: 'scriptfileToLoad' // default 'main'
}]
... some other stuff ...
});
To load your module you just need to use your 'packagename' at the requirements:
define(['jquery', 'packagename'], function($, MyPackage) {
MyPackage.useIt()
});
In your package you must use the ./ prefix to load your files relative to your submodule:
define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) {
LocalFile.finallyLoaded();
});
There is a useful shortcut: If your package name equals to your location and your main file is called 'main.js', then you can replace this
packages: [
{ name: 'packagename',
location: 'packagename',
main: 'main'
}]
to this:
packages: ['packagename']
As far as I can see, you already tried to define a package but did you also use the ./ prefix? Without this prefix require will try to find the files in it's global root-path. And without a package, ./ will be useless because the relative path is the same as the global root-path.
Cheers
I figured out the answer to my question, and the solution (they were not the same apparently). I guess I'll post it here in case it can help someone else in the future.
Essentially what I was wanting was to load my framework within its own context. I found the context option under the configuration section on require's website and an example of how to use it. Originally I tried this by doing something like:
var req = require.config({
baseUrl: 'framework',
context: 'framework',
paths: {
jQuery: 'lib/jquery/jquery-1.7.min.js',
Underscore: 'lib/underscore/underscore.min.js',
Backbone: 'lib/backbone/backbone.min.js',
etc...
}
});
req(['main'], function() {});
There were two problems with this. First, my 'req' variable was being defined outside of the framework, but I wanted the framework to define it's own paths. And second, whenever a file outside of the framework would require a file within the framework, which would in turn require 'jQuery', for example, then jQuery (or whatever else) wouldn't be required from within the context of the framework instance of require and so it couldn't find the file.
What I ended up doing was defining my framework's main.js to look something like this:
var paths = {
jQuery: 'lib/jquery/jquery-1.7.min.js',
Underscore: 'lib/underscore/underscore.min.js',
Backbone: 'lib/backbone/backbone.min.js',
etc...
};
define(function() {
var exports = {};
exports.initialize = function(baseUrl, overridePaths, callback) {
if(!overridePaths) {
overridePaths = {};
}
if(baseUrl && baseUrl[baseUrl.length - 1] != '/') {
baseUrl = baseUrl + '/';
}
var fullpaths = {};
for(var path in paths) {
// Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash
if(paths[path].match(/^(?:.*:\/\/|\/)/)) {
fullpaths[path] = paths[path];
}
else {
fullpaths[path] = baseUrl + paths[path];
}
}
var config = {paths: fullpaths};
for(var pathName in overridePaths) {
config.paths[pathName] = overridePaths[pathName];
}
require.config(config);
// Do anything else you need to do such as defining more functions for exports
if(callback) {
callback();
}
}
return exports;
});
And then in my project's main.js file I just do this:
require(['framework/main'], function(framework) {
// NOTE: This setTimeout() call is used because, for whatever reason, if you make
// a 'require' call in here or in the framework without it, it will just hang
// and never actually go fetch the files in the browser. There's probably a
// better way to handle this, but I don't know what it is.
setTimeout(function() {
framework.initialize('framework', null, function() {
// Do stuff here
}
}, 0);
});
This takes whatever is passed in to the framework's initialize() method for 'baseURL' and prepends that to any paths that the framework defines that do not start with a forward slash or 'anything://', unless they are override paths. This allows the package using the framework to override things like 'jQuery'.
This worked for me, adding a "./" prefix to the module names:
define(function (require, exports, module) {
exports.createDash = function (dash, element) {
require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) {
return new DashView({
model : new DashModel(dash),
el : element ? element : window
});
});
};
});
A process that worked well for me for allowing a package with submodules to be used directly from data-main or from an outside framework, assuming that a main.js (or other package main) is called by a particular name, was to use var baseUrl = require.toUrl('packageName') + '/../' as a prefix to a require.config({ paths: { ... } }) configuration file. For instance:
var music21Base = require.toUrl('music21') + '/../';
require.config({ paths: {
'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min';
'subModuleLoader': music21Base + 'src/subModuleLoader';
} });
The setting of context: "xxx" worked fine for calling normal modules with ./modName but did not work for the paths argument for me.

Categories