I have a common.js that defines the config for RequireJS:
(function(requirejs) {
"use strict";
requirejs.config({
baseUrl: "/js",
paths: {
"jsRoutes": "http://localhost:8080/app/jsroutes"
},
shim: {
"jsRoutes": {
exports: "jsRoutes"
}
}
});
requirejs.onError = function(err) {
console.log(err);
};
})(requirejs);
I then have a main.js file that I try to use the jsRoutes path that I created:
require(["./common", "jsRoutes"], function (common, routes) {
// do something interesting
});
but I do not load the resource at http://localhost:8080/app/jsroutes instead it tries to load http://localhost:8080/js/jsRoutes.js when the main.js is executed. But this resouce doesn't exist and I get a 404.
How do I get the jsRoutes path to work correctly? Also do I need the shim (I'm not 100% sure)?
I can debug into the common.js file, so the paths should be being set, right?
Update 1
I believe that the paths should work as I have them defined shouldn't they?
Excerpt 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 characteristics, 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:".
Update 2
I may have misread the docs, I can solve the issue by defining the main.js like so:
require(["./common", "http://localhost:8080/app/jsroutes"], function (common, routes) {
// do something interesting
});
I was rather hoping not to have to pass round this rather unwieldy URL though.
Update 3
Further investigation of the docs revealed the following snippet:
requirejs.config({
enforceDefine: true,
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
}
});
//Later
require(['jquery'], function ($) {
//Do something with $ here
}, function (err) {
//The errback, error callback
//The error has a list of modules that failed
var failedId = err.requireModules && err.requireModules[0];
if (failedId === 'jquery') {
//undef is function only on the global requirejs object.
//Use it to clear internal knowledge of jQuery. Any modules
//that were dependent on jQuery and in the middle of loading
//will not be loaded yet, they will wait until a valid jQuery
//does load.
requirejs.undef(failedId);
//Set the path to jQuery to local path
requirejs.config({
paths: {
jquery: 'local/jquery'
}
});
//Try again. Note that the above require callback
//with the "Do something with $ here" comment will
//be called if this new attempt to load jQuery succeeds.
require(['jquery'], function () {});
} else {
//Some other error. Maybe show message to the user.
}
});
It would seem here that the jquery path is working with a full URL
I'm fairly certain your path should be relative to your baseUrl. So giving it the domain & port is screwing it up.
EDIT: My standard require js config... it might help?
require.config({
baseUrl : "./",
paths: {
// Bower Components
respond: 'assets/bower_components/respond/dest/respond.min',
// Libraries & Polyfills
polyfillGCS: 'assets/js/lib/polyfill-getComputedStyle',
polyfillRAF: 'assets/js/lib/polyfill-requestAnimationFrame',
polyfillPro: 'assets/js/lib/polyfill-promise',
easing: 'assets/js/lib/easing',
signalsui: 'assets/js/lib/Signals.ui',
signalsjs: 'assets/js/lib/Signals',
domReady: 'assets/js/lib/domReady', // TODO: Still needed?
// Modules
app: 'assets/js/es5/app'
},
shim: {
app: {
deps: ['signalsjs']
},
signalsjs: {
deps: ['easing', 'polyfillGCS', 'polyfillRAF']
},
signalsui: {
deps: ['signalsjs']
}
}
});
// Load the app
require(['app']);
Ok I realised what I was doing wrong. It was simple really.
I had dependencies for ./common and jsRoutes being passed to the same module so jsRoutes was being required before it had been defined by the config.
I moved the dependency from the main.js file to where it was actually needed and things worked as I expected.
I had the same problem but I fixed it by changing my code like your original code:
require(["./common", "jsRoutes"], function (common, routes) {
// do something interesting
});
to this:
require(["./common"], function (common) {
require(["jsRoutes"], function (routes) {
// do something interesting
});
});
I'm guessing that, in the original code, RequireJS attempts to load the "jsRoutes" dependency before the configuration changes made in "common" are applied. Nesting the require calls effectively ensures that the second dependency is loaded only after the first is evaluated.
Related
I am trying to use a js library but am having trouble getting it connected.
https://github.com/Vibrant-Colors/node-vibrant
Downloaded vibrant.js using node.
Js file: var Vibrant = require(['node-vibrant']);
Html file (added this so I can ise require above): <script src="https://requirejs.org/docs/release/2.3.6/minified/require.js"></script>
And I am getting these errors:
There are two things here.
First one is that require() function does not return the module you are requiring, it works async. So you would have to provide a callback which will be executed when the module is loaded:
require(['node-vibrant'], () => {
console.log('Vibrant is loaded');
});
Second thing is your web server does not know what is /node-vibrant, you have to provide full path to it. As someone mentioned in comment, you can use CDN:
requirejs.config({
paths: {
'node-vibrant': 'https://cdnjs.cloudflare.com/ajax/libs/vibrant.js/1.0.0/Vibrant.min'
}
});
require(['node-vibrant'], () => {
console.log('Vibrant is loaded, you can do what you want with it');
console.log(window.Vibrant);
});
Third thing, which is optional is to set shim for this script as it is not AMD module. It won't be injected into your callback, but it will be a global variable. This can be fixed:
requirejs.config({
paths: {
'node-vibrant': 'https://cdnjs.cloudflare.com/ajax/libs/vibrant.js/1.0.0/Vibrant.min'
},
shim: {
'node-vibrant': {
'exports': 'Vibrant'
}
}
});
require(['node-vibrant'], (Vibrant) => {
console.log('Vibrant is loaded and injected, you can do what you want with it');
console.log(Vibrant);
});
I have such a code:
requirejs.config({
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
mods: 'default',
myFriend: 'myFriend',
myCoworker: 'myCoworker'
},
shim: {
mods: ['myFriend', 'myCoworker']
}
});
require(['mods'], function (mods) {
// something to do
});
and modules which are the dependencies:
myFriend.js
var mess = `<a really huge text, almost 200 Kbytes>`
console.log('This code is ran in the myFriend module...', {mess:mess});
myCoworker.js
console.log('This code is ran in the myCoworker module...');
var wrk = {
name: 'John'
};
So I hope, that accordingly to shim is should always load myFriend.js (that is checked by console.output) before myCoworker.js. But it doesn't. The console output shows:
This code is run in the myCoworker module...
and then
This code is run in the myFriend module...
Probably I have missed something, but what?
The entire code is here: http://embed.plnkr.co/zjQhBdOJCgg8QuPZ5Q8A/
Your dealing with a fundamental misconception in how RequireJS works. We use shim for files that do not call define. Using shim makes it so that RequireJS will, so to speak, add a kind of "virtual define" to those files. The shim you show is equivalent to:
define(['myFriend', 'myCoworker'], function (...) {...});
The dependency list passed to a define or require call does not, in and of itself, specifies a loading order among the modules listed in the dependency list. The only thing the dependency list does is specify that the modules in the list must be loaded before calling the callback. That's all.
If you want myFriend to load first, you need to make myCoworker dependent on it:
shim: {
mods: ['myFriend', 'myCoworker'],
myCoworker: ['myFriend'],
}
By the way, shim is really meant to be used for code you do not control. For your own code you should be using define in your code instead of setting a shim in the configuration.
I am trying to integrate requirejs framework to my app.
Is possible to create a virtual module (which doesn't exists as a physically file), where i could group all the jquery-validation plugins together?
For example, i need to load 4 dependencies everytime i want to use jquery-validate.
Instead of requesting them, each time, i create a jquery-val "virtual module", which should request all the dependencies automatically.
However, trying to load "jquery-val" actually tries to load the file from disk (which i don't have).
What should be the best practice in solving this issue?
// config
requirejs.config({
baseUrl: '/Content',
paths: {
'jquery': 'frameworks/jquery-3.1.1.min',
"jquery-validate": "frameworks/jquery.validate.min",
"jquery-validate-unobtrusive": "frameworks/jquery.validate.unobtrusive.min",
"jquery-unobtrusive-ajax": "frameworks/jquery.unobtrusive-ajax.min"
},
shim: {
"jquery-val": ["jquery", "jquery-validate", "jquery-validate-unobtrusive", "jquery-unobtrusive-ajax"]
}
});
// Solution 1: working, but ugly
define(["jquery", "jquery-validate-unobtrusive", "jquery-unobtrusive-ajax"], function ($) {
// My Module
});
// Solution 2: not working
define(["jquery-val"], function () {
// My Module
});
// Solution 3: create jquery-val.js file, which loads the dependencies automatically
// jquery-val.js
(function (global) {
define(["jquery", "jquery-validate-unobtrusive", "jquery-unobtrusive-ajax"], function ($) {
});
}(this));
take some time and read:
http://requirejs.org/docs/api.html#modulenotes
One module per file.: Only one module should be defined per JavaScript file, given the nature of the module name-to-file-path lookup algorithm. You shoud only use the optimization tool to group multiple modules into optimized files.
Optimization Tool
To answer your question:
It is good practice to define one module per file, so you don't need to define explicit a name for the module AND do the need for inserting it somewhere to be available before the other modules are loaded.
So you could require just the file: require("../services/myGroupModule") and this file would hold your module and requireJS would take care of the loading dependencies (and later the optimizations for concatenating into one file!). Here the module name is the file name.
You could nevertheless do the following and loading it as a file module or like you tried to define it beforehand and give the module a name:
//Explicitly defines the "foo/title" module:
define("myGroupModule",
["dependency1", "dependency2"],
function(dependency1, dependency2) {
return function myGroupModule {
return {
doSomething: function () { console.log("hey"); }
}
}
}
);
Maybe you should also give a look at some new module loaders:
WebPack 2: https://webpack.js.org/
SystemJS: https://github.com/systemjs/systemjs
Here is my main.js
requirejs.config({
baseUrl: '/js',
paths: {
jquery: 'jquery',
ckeditor: 'ckeditor/ckeditor',
juiAutocomplete: 'jquery-ui-1.10.4.custom',
tags: 'bootstrap-tokenfield',
createPost: 'createPost',
domReady: 'domReady',
test: 'dropUpload'
},
shim: {
createPost: {
deps: ['domReady!']
}
},
deps: ['require'],
callback: function(require) {
'use strice';
var moduleName = location.pathname.replace(/\//g, '-').replace(/^-/, '');
console.log('moduleName is: ' + moduleName);
console.log('yes is: ' + require.config);
}
});
In the callback, I'd like to access the paths which is defined in the requirejs.config() above. If it is possible, how to do it?
My purpose is to see if a module path is defined(exists). If so, then load the module script. If not checked, then a loading error will generate in the console.
Here are the available methods in requirejs by this console command. I can't find a way to access the paths I defined in requirejs.config(). Is this the right direction?
for (var i in requirejs) {console.log(i);}
config
nextTick
version
jsExtRegExp
isBrowser
s
toUrl
undef
defined
specified
onError
createNode
load
exec
undef
There is no public API to get the whole RequireJS configuration from inside a module. You can have a config section in your configuration, which modules may access.
However, the problem you describe trying to solve does not require you to read the configuration. Calling require the normal way will load the module. If the module can't be loaded, it will generate an error on the console. Presumably you also want your code to know whether the loading was successful or not. You can do it with an errback:
require(['foo'], function (foo) {
// Whatever you'd like to do with foo on success.
}, function (err) {
// Whatever you'd like to do on error.
});
If for some reason you must read the config directly then it is located at requirejs.s.contexts.<context name>.config where <context name> is the name of the RequireJS context. The default context is named _ so the configuration for it would be requirejs.s.contexts._.config. However, this is not part of the public API and can change at any time.
When building and running RequireJS with CoffeeScript in what I understand to be the ordinary way, I seem to have a problem with code not being executed in the expected order i.e.
<script src="/_s/lib/require-jquery.js"></script>
<script>
require.config({
paths: {
"main": "/_s/all.min", // <--- the 'optimized' result of `$ r.js build.js`
}
});
require(["main"], function () {
// this executes without any regard to whether 'main' is loaded.
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// also:
// require('cs!csmain') throws an exception because "cs!csmain" has not been
// loaded for context: '_'.
});
One would expect the function passed to require(["main"], ... to be executed after main and all its dependencies are loaded, because that's what the documentation says.
However, that is not the case at all. On my local development system this problem does not exhibit itself, I suppose because it is a race condition of some sort, making it doubly problematic because this is cropping up only AFTER deployment/staging.
I have a straightforward main.js like this:
var _paths;
_paths = {
...
underscore: '../lib/lodash'
};
require.config({
baseUrl: '/_s/mycode/', // main.js lives here
paths: _paths,
shim: {
...
'timeago': ['jquery']
},
waitSeconds: 60
});
require(['cs!csmain']); // has all the dependencies
Along with a build.js called as an argument to r.js along the lines of:
({
baseUrl: 'mycode',
optimize: 'none',
out: 'all.min.js',
stubModules: ['cs', 'coffee-script'],
paths: {
...
underscore: '../lib/lodash'
},
name: 'main',
shim: {
...
}
})
Does anyone have any idea what's going on here? I really enjoy the asynchronous nature of RequireJS combined with the ability to split up my code into sensible modules, but this problem is particularly frustrating because it only exhibits on a staging/production setting.
Any thoughts and suggestions would be duly appreciated.
EDIT: Removed some probably-superfluous arguments to shorten the question.
I believe I have sorted this problem out - main.js should contain a call to define, as I posted in an issue on GitHub.