How to use jQuery in chrome extension?
Solution 1
You have to add your jquery script to your chrome-extension project and to the background
section of your manifest.json like this :
"background":
{
"scripts": ["thirdParty/jquery-2.0.3.js", "background.js"]
}
If you need jquery in a content_scripts, you have to add it in the manifest too:
"content_scripts":
[
{
"matches":["http://website*"],
"js":["thirdParty/jquery.1.10.2.min.js", "script.js"],
"css": ["css/style.css"],
"run_at": "document_end"
}
]
This is what I did.
Also, if I recall correctly, the background scripts are executed in a background window that you can open via chrome://extensions
.
Solution 2
Its very easy just do the following:
add the following line in your manifest.json
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",
Now you are free to load jQuery directly from url
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
Source: google doc
Solution 3
And it works fine, but I am having the concern whether the scripts added to be executed in this manner are being executed asynchronously. If yes then it can happen that work.js runs even before jQuery (or other libraries which I may add in future).
That shouldn't really be a concern: you queue up scripts to be executed in a certain JS context, and that context can't have a race condition as it's single-threaded.
However, the proper way to eliminate this concern is to chain the calls:
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript({
file: 'thirdParty/jquery-2.0.3.js'
}, function() {
// Guaranteed to execute only after the previous script returns
chrome.tabs.executeScript({
file: 'work.js'
});
});
});
Or, generalized:
function injectScripts(scripts, callback) {
if(scripts.length) {
var script = scripts.shift();
chrome.tabs.executeScript({file: script}, function() {
if(chrome.runtime.lastError && typeof callback === "function") {
callback(false); // Injection failed
}
injectScripts(scripts, callback);
});
} else {
if(typeof callback === "function") {
callback(true);
}
}
}
injectScripts(["thirdParty/jquery-2.0.3.js", "work.js"], doSomethingElse);
Or, promisified (and brought more in line with the proper signature):
function injectScript(tabId, injectDetails) {
return new Promise((resolve, reject) => {
chrome.tabs.executeScript(tabId, injectDetails, (data) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError.message);
} else {
resolve(data);
}
});
});
}
injectScript(null, {file: "thirdParty/jquery-2.0.3.js"}).then(
() => injectScript(null, {file: "work.js"})
).then(
() => doSomethingElse
).catch(
(error) => console.error(error)
);
Or, why the heck not, async
/await
-ed for even clearer syntax:
function injectScript(tabId, injectDetails) {
return new Promise((resolve, reject) => {
chrome.tabs.executeScript(tabId, injectDetails, (data) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError.message);
} else {
resolve(data);
}
});
});
}
try {
await injectScript(null, {file: "thirdParty/jquery-2.0.3.js"});
await injectScript(null, {file: "work.js"});
doSomethingElse();
} catch (err) {
console.error(err);
}
Note, in Firefox you can just use browser.tabs.executeScript
as it will return a Promise.
Solution 4
Apart from the solutions already mentioned, you can also download jquery.min.js
locally and then use it -
For downloading -
wget "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"
manifest.json -
"content_scripts": [
{
"js": ["/path/to/jquery.min.js", ...]
}
],
in html -
<script src="/path/to/jquery.min.js"></script>
Reference - https://developer.chrome.com/extensions/contentSecurityPolicy
Solution 5
In my case got a working solution through Cross-document Messaging (XDM) and Executing Chrome extension onclick instead of page load.
manifest.json
{
"name": "JQuery Light",
"version": "1",
"manifest_version": 2,
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts": [
{
"matches": [
"https://*.google.com/*"
],
"js": [
"jquery-3.3.1.min.js",
"myscript.js"
]
}
],
"background": {
"scripts": [
"background.js"
]
}
}
background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
});
});
myscript.js
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.message === "clicked_browser_action") {
console.log('Hello world!')
}
}
);
Related videos on Youtube
Ishan
I make applications running on the entire tech stack from consumer-facing devices to the machines supporting those devices. I try to keep optimizing the performance of the devices/servers that my programs run on. Currently working as a Senior Software Engineer at Myntra.
Updated on December 15, 2021Comments
-
Ishan over 2 years
I am writing a chrome extension. And I want to use
jQuery
in my extension. I am not using any background page, just a background script.Here are my files :
manifest.json
{ "manifest_version": 2, "name": "Extension name", "description": "This extension does something,", "version": "0.1", "permissions": [ "activeTab" ], "browser_action": { "default_icon": "images/icon_128.png" }, "background": { "scripts": ["background.js"], "persistent": false }, "icons": { "16": "images/icon_16.png", "48": "images/icon_48.png", "128": "images/icon_128.png" } }
My
background.js
file just runs another file namedwork.js
// Respond to the click on extension Icon chrome.browserAction.onClicked.addListener(function (tab) { chrome.tabs.executeScript({ file: 'work.js' }); });
The main logic of my extension is inside
work.js
. The contents of which I don't think matters here for this question.What I want to ask is how can I use jQuery in my extension. Since I am not using any background page. I can't just add jQuery to it. So how can I add and use jQuery into my extension ?
I tried running jQuery along with my work.js from
background.js
file.// Respond to the click on extension Icon chrome.browserAction.onClicked.addListener(function (tab) { chrome.tabs.executeScript({ file: 'thirdParty/jquery-2.0.3.js' }); chrome.tabs.executeScript({ file: 'work.js' }); });
And it works fine, but I am having the concern whether the scripts added to be executed in this manner are being executed asynchronously. If yes then it can happen that work.js runs even before jQuery (or other libraries which I may add in future).
And I would also like to know what's the correct and best way to use third party libraries, in my chrome extension.
-
bjb568 over 9 yearsThe correct way is to go vanilla!
-
Pro Q over 7 yearsIf you are here looking for how to add jQuery to a pop-up extension (as I was), see this question: stackoverflow.com/questions/12035242/…
-
-
Ishan over 10 yearsWell what do you exactly mean by
You have to add your jquery script to your chrome-extension project
? I did this : manifest.json :"background": {
` "scripts": ["thirdParty/jquery-2.0.3.js", "background.js"],` ` "persistent": false` ` },` and I have downloaded the jQuery to thirdParty folder. However I still can't use jQuery. It give the error :Uncaught ReferenceError: $ is not defined
my added this to mywork.js
file for testing.$("body").html("Foo!");
-
Ishan over 10 yearsThe above comment looks like a mess but while adding comments preview is not shown. Please forgive me for that.
-
Nico over 10 yearsI mean to add it to your chrome-extension folder. Like /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. You should do the same thing with your work.js.
-
Ishan over 10 yearsI tried doing what you said. But I am still getting the same error of not being able to access jquery from my
work.js
file.Uncaught ReferenceError: $ is not defined
. If you can, can you please upload a working example somewhere. Just a simple example like doing '$("body").html("Foo!");' in work.js. -
Nico over 10 years@ishan I can't really help you, this is what I did and I have jquery in my background.js script.
-
Nico over 10 years@ishan Have you tried to add
{"runAt":"document_end"}
in yourchrome.tabs.executeScript
call ? Likechrome.tabs.executeScript({file: 'work.js', runAt:'document_end'})
-
BenR over 9 yearsI also had trouble getting
jQuery
or$
to be recognized. Turned out I was referencing jQuery last in the manifest array. When I put it first it was recognized. -
user889030 about 9 yearsin your chrome extension project folder , make your have thirdParty folder and you have jquery.1.10.2.min.js file in it (( thirdParty/jquery.1.10.2.min.js ))
-
alayli almost 9 yearsPage already has jQuery. Is there a way to use web site's jQuery?
-
Nico almost 9 years@alayli I'm not sure about this but the background page is a page of it's own so it needs the lib. The content script should be able to use whatever is publicly available in the page it is injected. I think you don't necessarily need a background page so if you want your extension to depends on the injected page dependency, it's up to you.
-
another over 7 yearsWhat if you have multiple scripts to load?
-
D. Woods almost 7 years@BenR - Your comment is truly a solution (at least for my needs with respect to getting a script loaded via
content_script
to find and use functions from the jQuery library). -
c-an over 5 yearsThis is the best way... You don't need the html part.
-
Nathaniel Verhaaren about 5 yearsGreat answer if you want to load your script from a remote server (which effectively requires that you trust the remote server with your extension and everything it has access to).
-
Dan Atkinson almost 5 years@NathanielVerhaaren This is a reasonable point to raise, but it can be mitigated by verifying the source using
subresource integrity
(SRI). -
FriskySaga about 4 yearsThe first method is brilliant. As someone who doesn't know much JavaScript, I never considered something like that.
-
Manik over 3 yearsin manifest V3 this manifest will give this error:
The "background.scripts" key cannot be used with manifest_version 3. Use the "background.service_worker" key instead. Could not load manifest.
so we have to use background.service_workers like this:background": {"service_workers": ["thirdParty/jquery-2.0.3.js", "background.js"]}