I'm trying to load a JS file from a bookmarklet. The JS file has this JS that wraps the module:
(function (root, factory) {
if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals
root.moduleGlobal = factory();
}
}(this, function factory() {
// module script is in here
return moduleGlobal;
}));
Because of this, if the webpage uses RequireJS, the script will not export a global when it loads. To get around this I temporarily set define
to null
, load the script, then reset define
to its original value:
function loadScript(url, cb) {
var s = document.createElement('script');
s.src = url;
s.defer = true;
var avoidRequireJS = typeof define === 'function' && define.amd;
if (avoidRequireJS) {
var defineTmp = define;
define = null;
}
s.onload = function() {
if (avoidRequireJS) define = defineTmp;
cb();
};
document.body.appendChild(s);
}
This works, but it seems to me like it could be problematic to change a global variable when other parts of the application could depend on it. Is there a better way to go about this?
You may fetch the script using XMLHttpRequest
, jQuery.ajax
or the new Fetch
API.
This will allow you to manipulate the script and reassign define
before executing it. Two options:
Have the module export a global by wrapping the script with:
(function(define){ ... })(null);
Handle the module exports yourself by wrapping the script with:
(function(define, module){ ... })((function() {
function define(factory) {
var exports = factory();
}
define.amd = true;
return define;
})());
You can then load it using a new <script>
element or 😲.eval
Note that when using XHR, you may have to address CORS issues.