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.
Related
Question#1: After requirejs configuration, what will be the format of first require() call to load my main.js
App.js
requirejs.config({
baseUrl: 'lib',
paths: {
app: '../app'
}
});
require(['app/main'], function(m){
console.log('loading m...');
});
Question#2: And what will be format of first define() function in main.js file.
Main.js
define(function () {
var messages = require('./messages');
var print = require('print');
});
The only issue I see in the code you show is that your main.js should have its define call like this:
define(function (require) {
var messages = require('./messages');
var print = require('print');
});
If you pass a function as the first parameter to define, RequireJS will call it with the special modules require, exports and module but at a minimum you must declare the first parameter so that the calls you made inside your factory function are to the local require (passed to the function) rather than the global require. There are a number of issues if you call the global require. One of them is that relative module references like ./messages won't be resolved correctly.
The require call you have in your app.js looks fine.
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
Script A
;(function(g){
define('hotness', [], function() {
function f() {;
console.log('gotem');
}
return f;
});
define('otherModule', [], function() {});
})(this);
Script B
define([
'ScriptA',
], function() {
var hotness = require('hotness')
});
Error: Module name "hotness" has not been loaded yet for context: _
What is the recommended way to require in a definition from ScriptA in ScriptB?
I've also tried:
Script B Alt
define([
'require',
'ScriptA',
'hotness'
], function(require) {
var hotness = require('hotness')
});
Which gives me
Error loading resource ... /hotness.js: No such file or directory
Error: Script error for: hotness
EDIT:
It's important to note that ScriptA stands as is and will not be modified. The question is how can I get at the named module in ScriptA from ScriptB.
EDIT2:
I have no control over the HTML or any other aspect of the page. I must do everything within ScriptB.
EDIT3:
I have an example of something that works but it looks like a horrible antipattern work-around so I didn't even want to mention it:
define(['require'], function(require) {
// why use window? IDK.
// this is just verbatim what is "working" for someone else
window.require(['scriptA'], function(sA) {
//sA never actually used
window.require([
'otherModule'
], function(oM) {
var hotness = require('hotness'),
You should use a bundles configuration. Given what you've described works, you should use:
bundles: {
'scriptA': ['hotness', 'otherModule']
}
This essentially tells RequireJS "when you want to find hotness or otherModule then load scriptA because they are defined there". I use this every now and then to load modules from bundles that have been generated with r.js.
Other than this Joseph the Dreamer is correct that you should not in the same module mix the AMD and CommonJS methods of getting dependencies.
Your ScriptA uses named modules. They must be loaded after RequireJS but prior to any of the dependents. RequireJS does not recommend named modules unless you know what you're doing (like load a library like a regular script, and register it as a module at the same time).
Error: Module name "hotness" has not been loaded yet for context: _
This is a generic RequireJS error, when the module is loaded from the server, but somehow RequireJS can't provide it to the dependent. Usually happens when the module has syntax errors or when there's a circular dependency, among others.
ScriptB also has problems. It's trying to use both AMD style (array dependencies) and CommonJS style (explicit require). Just use one of the two syntaxes. Note that in the CommonJS format, it needs the module to have a first argument named require to trigger CommonJS format of writing.
define(['hotness'], function(hotness) {
// use hotness
});
// or
define(function(require){
var hotness = require('hotness');
// use hotness
});
Error loading resource ... /hotness.js: No such file or directory
Be sure to set a base url. It can be implicit (based on the data-main location) or explicit (using require.config). Module names are usually paths + filenames relative to the base url.
It is advised that you use one file per module, containing a module definition that has no name (the file name becomes the name of the module) and resides somewhere under the set baseUrl.
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.
I have a Workout object and a WorkoutSection object. Both use the other for various attributes. The Workout does not use WorkoutSection during load, however WorkoutSection uses Workout during load.
WorkoutSection.js
define(['require',
// post-load
'models/Workout'
],
function(require) {
// must require Workout because of mutual dependency
var Workout = require('models/Workout');
Workout.js
define([
'require','models/WorkoutSection'
],
function(require) {
// must re-require Workout because of mutual dependency
var WorkoutSection;
var Workout = Parse.Object.extend("Workout",
{
initialize : function() {
WorkoutSection = require('models/WorkoutSection');
},
The error:
Uncaught Error: Module name "models/Workout" has not been loaded yet
for context: _ http://requirejs.org/docs/errors.html#notloaded
require.js:2 H require.js:2 k.s.newContext.j.require require.js:2
requirejs require.js:2 (anonymous function) WorkoutSection.js:20
I am following the solution described in the link, but am still getting the error =S Any ideas that would fix this?
Here's my main.js:
// Filename: main.js
// Require.js allows us to configure shortcut alias
// Their usage will become more apparent futher along in the tutorial.
require.config( {
paths : {
jQuery : 'libs/jquery/jquery-min',
Underscore : 'libs/underscore/underscore-min',
Backbone : 'libs/backbone/backbone-min',
Parse : 'libs/parse/parse-min',
templates : '../templates'
}
});
require( [
// Load our app module and pass it to our definition function
'app',
],
function(App) {
// The "app" dependency is passed in as "App"
// Again, the other dependencies passed in are not "AMD" therefore
// don't pass a parameter to this function
App.initialize();
});
Thanks!
I suggest you either:
try reworking WorkoutSection.js into the CommonJS format as documented here: http://requirejs.org/docs/api.html#cjsmodule
Completely exclude models/WorkoutSection as a dependency of Workout.js