Chrome Extension RequireJS Content Scripts
If you are interested in using RequireJS in your Chrome Extension take a look at this handy starter repo template on Github.
The template has one key file require-cs.js
:
require.load = function (context, moduleName, url) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
eval(xhr.responseText);
context.completeLoad(moduleName)
}
};
xhr.send(null);
};
This will allow your content scripts to be loaded in the context of your extension rather than inserted in to the page where require is probably not defined.
Written by Jacob Gable
Related protips
3 Responses
Please correct me if I'm wrong but, doing so in a chrome extension already moved to the version 2 of the manifest (which is required for all the new extensions), without relaxing the CSP policies, shouldn't it generates a security exception due to the eval()
instruction?
BTW, this is the same problem in which most template libraries incur when they use new Function()
with default CSP manifest v2 policy.
As long as the eval()
is used in a content-script
it is fine. But, yes, I did run into that CSP issue with lodash and had to make it a web_accessible_resource
and use the mobile build to get it to run.
For background scripts I use an html file with a script tag that references my require.js
file and uses the data-main
attribute and everything seems fine without having to use the require-cs.js
file.
This errors occur if i use requirejs in chrome-extension. Without chrome-extension, also call over script-tag( <script data-main="js/main" src="js/lib/requirejs/require.js"></script> ) everything works well.
If i require('backbone') in test.js( see below ) i get an error --> Uncaught TypeError: Cannot call method 'each' of undefined ! i believe backbone cant call "each" method because underscore is not loaded completely ( see http://tinypic.com/view.php?pic=6j3a08&s=5 )
What am I doing wrong?
manifest.json file
{
"manifestversion": 2,
.....
.....
....
"contentscripts": [
{
"matches": ["<all_urls>"],
"js": [
"js/lib/requirejs/require.js",
"js/lib/requirejs/require-cs.js",
"js/main.js"
]
}
],
.....
.....
.....
}
main.js
requirejs.config({
baseUrl: chrome.extension.getURL("/"),
urlArgs: "v=" + (new Date()).getTime(),
paths: {
app : 'js/app',
jquery: 'js/lib/jquery/jquery',
backbone : 'js/lib/backbone/backbone',
underscore : 'js/lib/underscore/underscore'
},
shim : {
jquery : {
exports : '$'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
underscore : {
exports : '_'
}
}
});
require(['app/test'], function (test) {
console.log(test);
});
define() file test.js
define(function(require){
var $ = require('jquery');
$('body').append('<div id="foo">im appended over requirejs</div>');
$('body').on({
click : function(){
var Backbone = require('backbone');
console.log(Backbone);
}
}, '#foo');
return {
foo : 'foo',
hoo : 'huu'
};
});