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
Related
I'm using SweetAlert2 and on IE 11 throws exception:
This package requires a Promise library, please include a shim to
enable it in this browser (See:
https://github.com/sweetalert2/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2#1-ie-support)
Because IE 11 doesn't support Promises and needs to be added manually.
I'm using bluebird like so:
const Promise = require('bluebird');
const Swal = require('sweetalert2');
Swal.fire(...)
...
But still, sweetalert's check doesn't pass:
..
if (typeof Promise === 'undefined') {
error('This package requires a Promise library, please include a shim to enable it in this browser (See: https://github.com/sweetalert2/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2#1-ie-support)');
}
..
How to fix it? Thanks.
You can fix it with the following:
window.Promise = require('bluebird');
This will load Promise as a global variable of your window instead of the file like you did with the const.
I'm not sure how your file structure is, but if you have a file that loads all the dependencies, you can simply add the line above to the script that will be called before your other scripts.
For example:
// bootstrap.js
window.Promise = require('bluebird');
window.Swal = require('sweetalert2');
// app.js
require('./bootstrap');
Swal.fire(...);
For those who are using Sweetalert2 directly by referencing it in pages:
This could also be fixed by including the below core js lib after Sweetalert2 lib
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.js"></script>
I have a couple of AMD modules compiled using TypeScript's --outFile option into a single file:
define("partA", ["require", "exports"], function (require, exports) {
"use strict";
function partAFunc() {
console.log('partAFunc');
return 'partAFunc';
}
exports.partAFunc = partAFunc;
});
define("partB", ["require", "exports"], function (require, exports) {
"use strict";
exports.partB = 42;
});
define("partC", ["require", "exports"], function (require, exports) {
...
});
Now I want to load only the partA module and call its partAfunc() so I can do the following in Node.js:
SystemJS.config({
map: {
'main': 'my-bundle.js',
},
});
SystemJS.import('main').then((m) => {
SystemJS.import('partA').then((m) => {
m.partAFunc();
});
});
The first import SystemJS.import('main') just registers all the modules and then SystemJS.import('partA') works because module partA is already registered (or at least I guess that's what it does).
However, why I can't just use SystemJS.import('partA') and set the bundle as a dependency:
SystemJS.config({
meta: {
'partA': {
deps: [ 'my-bundle.js' ],
}
}
});
SystemJS.import('partA').then((m) => {
m.partAFunc();
});
The meta is completely ignored. The doc at https://github.com/systemjs/systemjs/blob/master/docs/config-api.md#meta says:
Dependencies to load before this module. Goes through regular paths and map normalization. Only supported for the cjs, amd and global formats.
It looks like SystemJS first checks whether the file partA exists (which obviously doesn't) and throws an error (I tested it with an existing file and the meta config worked):
(node:60981) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOENT: no such file or directory, open '/Users/.../partA'
Instantiating /Users/.../partA
Loading partA
I'd expect that also the following should work when the first variant works with two nested SystemJS.import calls.
SystemJS.config({
map: {
'partA': 'my-bundle.js',
},
});
SystemJS.import('partA').then((m) => {
// m.partAFunc();
console.log(m)
});
This prints an empty object. It looks like when there're more than one module in a single file it just registers them and doesn't load any of them?
I read all the documents in https://github.com/systemjs/systemjs/tree/master/docs but I think I'm still lost.
What you need to do is use the bundles setting and set your bundle like this:
bundles: {
'my-bundle.js': ['partA', 'partB', 'partC'],
},
Roughly, this tells SystemJS "when you look for module partA, fetch and execute the module named my-bundle.js and you'll find partA there."
Your approach using meta cannot work. Your meta setting does not say "don't try to fetch a module named partA and instead fetch my-bundle.js" it says "when you process partA, in addition to the dependencies it already has, add my-bundle.js to the list of dependencies." SystemJS will still fetch partA. There's no reason for it to wait until it has executed my-bundle.js before it tries to fetch it, so it launches the fetch immediately and it fails.
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!
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 am trying to test a simple node Module with intern.The module is an AMD module. I am running into a couple of issues
If the module is defined as below, I get the error "moduleName" has
no method 'map' "
define('moduleName',[]function(require){ var r= require('request');
})
If the module is defined as below without a moduleName, I see this
error "undefined is not a function" - I guess its not able to resolve 'require'
define([]function(require){ var r= require('request'); })
Here is how my Test Looks
define([
'intern!object',
'intern/chai!assert',
'/src/api/nameApi'
], function (registerSuite, assert,nameApi) {
registerSuite({
name: 'GetName Test',
getName: function () {
var nameFromApi = nameApi.getName();
assert( nameFromApi!= null,'name is not null');
}
});
});
Providing an explicit module ID as the first argument to define destroys module portability and shouldn’t be done. It is not currently supported by the loader used by the master branch because it is such a bad idea. It is supported by the geezer branch, but again, I strongly advise you to never use this pattern.
The second module definition you have provided is just wrong; you need to put 'require' in your dependencies array if you expect to load the special require function. You also can’t use a variable to pass a module ID to the require function if you are expecting it to be pre-loaded as a dependency. So, it should look like this:
define(['require', 'foo'], function (require) {
var foo = require('foo');
});
or, using the CommonJS compatibility wrapper syntax, where require is implicitly provided:
define(function (require) {
var r = require('foo');
});
EDIT: Also, now that you have added the test module: within your test’s define, '/src/api/nameApi' is not a valid AMD module identifier.