I am trying to run a widget on a web page that leverages the Q library. Unfortunately, the page also uses the AddThis widget which embeds require.js and is causing a conflict. Specifically, when run together the two following error messages are displayed in the console:
Uncaught ReferenceError: Q is not defined
Uncaught Error: Mismatched anonymous define() module
Unfortunately, I don't have control over the use of the AddThis widget. However, I do have control over the embedded application using Q. Is there a JavaScript pattern that I can implement to namespace the Q library so that it will not conflict with require.js?
Here is a simple example that demonstrates the problem:
<!doctype html />
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.15/require.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.min.js"></script>
</head>
<body>
<script>
var called = function() {
var deferred = Q.defer();
console.log("Q called successfully");
deferred.resolve();
return deferred.promise;
}
Q.fcall(called);
</script>
</body>
</html>
I'll preface this by saying I'm not familiar with "AddThis", and wouldn't call myself an expert on Require, but I'll try to work through the layers of problems you've got in this situation.
First, when Q finds require, it doesn't put itself in the global namespace, but just calls define with the Q module. This creates an anonymous module within require which is loaded by calling require using the path of that file. This is a common pattern for modules that might be used in non-browser environments. When you comment out that block, it goes down to the "script" module loader, where it creates an instance of the Q module and sets it on self. In the browser, this is (apparently) aliased to window.
So, how do we solve this problem without commenting out parts of the module junk in q.js?
You SHOULD be able to use Require's shim configuration to export Q to the global scope, which would look like this:
require.config({
shim: {
Q: {
exports: "Q"
}
}
});
But there's 2 problems with this. Firstly, you're not in control of the require config, right? It's loaded by the "AddThis" plugin. Secondly, exporting Q from a shim config doesn't even seem to work for Q, possibly because Q uses "define" internally ( Require says that scripts using "define" internally might not be shimmed properly. This might also be what's triggering your "Mismatched anonymous define() module" error ). It's weird that there doesn't seem to be any other SO questions or issues on Q's github about this lack of shim-ability. I'm not sure if Q is doing something "wrong" or I'm just crazy. Maybe someone who knows a little more about module shimming could comment on that.
In any case, you can't shim it here. You should be able to do something like this:
if ( require ){
require(['path/to/Q'],function(Q){ window.Q = Q; });
}
This will explicitly require Q only if require exists and save it to the window variable so you can use it wherever.
However, this also has a problem. The "path/to/Q" here will be relative to any baseUrl set in that require's config. So, if "AddThis" is setting the baseUrl to be some weird path for that plugin where it's hard for you to get at Q, then you might have to solve that problem.
You might be able to use Require's multiversion ability to set your own config where you specify your own baseUrl:
if ( require ){
var myRequire = require.config({
baseUrl: '/my/local/root',
paths: {
Q: 'path/to/Q'
}
});
myRequire(['Q'],function(Q){
window.Q = Q;
bootstrapMyApp();
});
}
else {
bootstrapMyApp();
}
This is completely untested, but it seems like it might work!
Related
I am running a purely JavaScript project (not using node) and I need to load a module for Promises called Bluebird.
I'm not experienced in loading modules with JavaScript, I've always used mean stack in the past.
I have the following in index.html:
<script data-main="assets/js/app/App.js" src="assets/js/vendor/require.js"></script>
<script src="assets/js/app/App.js"></script>
I read online that in my App.js I should have:
define(["bluebird"],function(Promise){
//load modules
});
The problem is that I don't know what to put in place of "//load modules" to load up the bluebird.js. I've tried using:
define(["bluebird"],function(Promise){
Promise = require('bluebird');
});
But this has the error:
require.js:5 Uncaught Error: Mismatched anonymous define() module: function (Promise){
Promise = require('bluebird');
}
Note that I did try just using var Promise = require('bluebird'); but this returned Uncaught Error: Module name "bluebird" has not been loaded yet for context: _. Use require([])
Ends up my original code from the requirejs error doc was correct but I had problems in my index.html which were causing it to fail.
The correct way to include bluebird would be:
require(['bluebird'], function (Promise) { //module loaded });
In //module loaded you need to put the bulk of the App.js code.
You need to make sure you don't include a for bluebird either if requirejs is loading it.
Here is another way to do it:
define(function (require) {
"use strict";
var Promise = require('bluebird');
...
}
Note that Bluebird module will NOT be delay loaded, this is simply a syntax sugar to make dependencies more readable.
Check
http://requirejs.org/docs/whyamd.html#sugar
I have a strange behaviour in require, that I dont know how to avoid (or maybe I have my basics wrong?).
Consider the following code:
define (require) ->
potoo = require "potoo"
service = require "communication.data"
downloadIfNeeded = ->
# ...
service.download()
new potoo.App
pageContainer: potoo.UI.NGStylePage
userRequired: true
stdRoute: "overview"
onLogin: downloadIfNeeded
This is not going to work, because 'communication.data' itself requires 'app' (the code shown). so we obviously have a circular dependency. That fails with a 'Uncaught Error: Module name "app" has not been loaded yet for context: _'
Since the downloadIfNeeded function doesn't get called until after the user actually clicks something, I figured, that something like the following should work:
define (require) ->
potoo = require "potoo"
downloadIfNeeded = ->
service = require "communication.data"
service.download()
...
But that actually throws the same error as above. To make it work, i have to use a little hack. I alias the require function with some other name:
define (require) ->
potoo = require "potoo"
reqs = require
downloadIfNeeded = ->
service = reqs "communication.data"
service.download()
...
Is this the best way to do so? Or would you recommend the CommonJS Style (module.export) that is also supported by requirejs.
I've done a test here and was able to find a solution. What you have is equivalent to this JavaScript:
define(function (require) {
This is enough to be able to use the (fake) synchronous form of require. However, RequireJS will give you the error you got when you try to use a synchronous require and you have circular dependencies. What you need is this:
define(function (require, exports, module) {
This is so that your module uses exports to export its values and consequently RequireJS has an object that can be updated when the module has finished initialized.
I`m using r.js to optimize my app,
as i saw in several samples, i used build.json configuration file to config my optimization options.
The problem is that when i set reference to the output javascript file after optimization I`m getting the following error in the browser:
Uncaught ReferenceError: define is not defined main-built.js:14735
Looks like, all my app modules are exists but RequireJs is missing.
This is my build.json configuration file:
{
"baseUrl": "../",
"name": "src/modules/main",
"include": ["src/modules/main", "src/modules/navbar/navbar", "src/modules/contact/contact", "src/modules/about/about"],
"exclude": [], "optimize": "none", "out": "main-built.js",
"insertRequire": ["src/modules/main"]
}
How do i add requirejs to the output js file? maybe i need to add something else to config? or maybe the problem is not the config?
Thanks,
Ori
Try:
<script src="scripts/require.js" data-main="scripts/main-built"></script>
If I understood correctly, this is how it should work.
What r.js does is that it compiles all RequireJS modules into a single file. However you still need to load that file with RequireJS script, for example:
<script data-main="scripts/main" src="scripts/require.js"></script>
So just add a minified version of require.js to your website and load the optimized module using that.
You have to include require.js if you have modularized your project using RequireJS:
<script data-main="scripts/main" src="scripts/require.js"></script>
This is because RequireJS handles the loading of modules and resolving dependencies. Without it, your browser does not know what define means. A way to get around this is to use UMD (Universal Module Definition). This makes it so that your module can be used with or without RequireJS. You can see many examples here. One that fits your use case is:
// Uses AMD or browser globals to create a module.
// If you want something that will also work in Node, see returnExports.js
// If you want to support other stricter CommonJS environments,
// or if you need to create a circular dependency, see commonJsStrict.js
// Defines a module "amdWeb" that depends another module called "b".
// Note that the name of the module is implied by the file name. It is best
// if the file name and the exported global have matching names.
// If the 'b' module also uses this type of boilerplate, then
// in the browser, it will create a global .b that is used below.
// If you do not want to support the browser global path, then you
// can remove the `root` use and the passing `this` as the first arg to
// the top function.
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else {
// Browser globals
root.amdWeb = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
I'm working on a project that requires that some custom Dojo widgets are loaded from another server.
I am wrapping everything with dojo._xdResourceLoaded(function() based on what was suggested at Dojo - Issue loading widget cross-domain
I do get this error
TypeError: dojo._xdResourceLoaded(...) is not a function but my widget works. Not sure why it is throwing this error
We are using dojo 1.6.
dojo._xdResourceLoaded(function(){
return {
depends: [
["provide", "widgets.test"],
["require", "dijit._Widget"],
["require", "dijit._Templated"]
],
defineResource: function(dojo) {
///////////////////////////////
/// Begin standard declaration
dojo.provide("widgets.test");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare("widgets.test", [dijit._Widget, dijit._Templated], {
// Our template - important!
templateString: dojo.cache("widgets.test", "templates/Widgettest.html"),
postCreate: function(){...
The reply in the linked thread is not really correct. Your code, like all user code, should not call underscored (private) methods of the Dojo object. These methods are intended for use by Dojo code only.
If you are writing modules that load dependencies cross-domain using the legacy XD loader, you need to require all of your cross-domain dependencies and then wrap your code that uses those dependencies in dojo.ready:
dojo.provide("widgets.test");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.ready(function () {
dojo.declare("widgets.test", [ dijit._Widget, dijit._Templated ], { /* … */ });
});
dojo.ready executes the callback once all the asynchronous dependencies are loaded.
Needless to say, AMD is much better than this, so upgrading to Dojo 1.7+ and using AMD modules would be the best solution as soon as you are capable.
Using RequireJS I'm building an app which make extensive use of widgets. For each widget I have at least 3 separate files:
request.js containing code for setting up request/response handlers to request a widget in another part of my application
controller.js containing handling between model and view
view.js containing handling between user and controller
Module definition in request.js:
define(['common/view/widget/entity/term/list/table/controller'],
function(WidgetController) { ... });
Module definition in controller.js:
define(['common/view/widget/entity/term/list/table/view'],
function(WidgetView) { ... });
Module definition of view.js is:
define(['module','require'],function(module,require) {
'use strict';
var WidgetView = <constructor definition>;
return WidgetView;
});
I have lots of these little situations as above in the case of widgets I have developed. What I dislike is using the full path every time when a module is requiring another module and both are located in the same folder. I'd like to simply specify as follows (assuming we have a RequireJS plugin which solves this for us):
define(['currentfolder!controller'],
function(WidgetController) { ... });
For this, I have written a small plugin, as I couldn't find it on the web:
define({
load: function (name, parentRequire, onload, config) {
var path = parentRequire.toUrl('.').substring(config.baseUrl.length) + '/' + name;
parentRequire([path], function (value) {
onload(value);
});
}
});
As you might notice, in its basic form it looks like the example of the RequireJS plugins documentation.
Now in some cases, the above works fine (e.g. from the request.js to the controller.js), but in other cases a load timeout occurs (from controller.js to view.js). When I look at the paths which are generated, all are proper RequireJS paths. Looking at the load timeouts, the following is logged:
Timestamp: 13-09-13 17:27:10
Error: Error: Load timeout for modules: currentfolder!view_unnormalized2,currentfolder!view
http://requirejs.org/docs/errors.html#timeout
Source File: http://localhost/app/vendor/requirejs/require.js?msv15z
Line: 159
The above log was from a test I did with only loading the view.js from controller.js using currentfolder!view in the list of modules in the define statement. Since I only requested currentfolder!view once, I'm confused as to why I both see currentfolder!view_unnormalized2 and currentfolder!view in the message.
Any idea as to why this might be happening?
My answer may not answer your primary questions, but it will help you achieve what you're trying to do with your plugin.
In fact, Require.js support relative paths for requiring modules when using CommonJS style. Like so:
define(function( require, exports, module ) {
var relativeModule = require("./subfolder/module");
module.exports = function() {
console.log( relativeModule );
};
});