Как использовать jQuery в расширении Chrome?
Я пишу расширение Chrome. И я хочу использовать jQuery
в моем расширении. Я не использую фоновую страницу, просто фоновый скрипт.
Вот мои файлы:
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"
}
}
мой background.js
файл просто запускает другой файл с именем work.js
// Respond to the click on extension Icon
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript({
file: 'work.js'
});
});
Основная логика моего расширения внутри work.js
, Содержание, которое я не думаю, имеет значение здесь для этого вопроса.
Я хочу спросить, как я могу использовать jQuery в своем расширении. Так как я не использую фоновую страницу. Я не могу просто добавить jQuery к нему. Итак, как я могу добавить и использовать jQuery в моем расширении?
Я попытался запустить jQuery вместе с моим work.js из background.js
файл.
// 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'
});
});
И это прекрасно работает, но меня беспокоит, выполняются ли сценарии, добавленные для выполнения таким образом, асинхронно. Если да, то может случиться так, что work.js запускается даже до jQuery (или других библиотек, которые я могу добавить в будущем).
И я также хотел бы знать, как правильно и лучше использовать сторонние библиотеки в моем расширении chrome.
7 ответов
Вы должны добавить свой jquery-скрипт в ваш проект chrome-extension и в background
раздел вашего manifest.json вот так:
"background":
{
"scripts": ["thirdParty/jquery-2.0.3.js", "background.js"]
}
Если вам нужен jquery в content_scripts, вы должны добавить его и в манифест:
"content_scripts":
[
{
"matches":["http://website*"],
"js":["thirdParty/jquery.1.10.2.min.js", "script.js"],
"css": ["css/style.css"],
"run_at": "document_end"
}
]
Это то, что я сделал.
Кроме того, если я правильно помню, фоновые скрипты выполняются в фоновом окне, которое вы можете открыть с помощью chrome://extensions
,
Это очень просто, просто сделайте следующее:
добавьте следующую строку в ваш mainfest.json
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",
Теперь вы можете загрузить JQuery непосредственно из URL
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
Источник: Google Doc
И это прекрасно работает, но меня беспокоит, выполняются ли сценарии, добавленные для выполнения таким образом, асинхронно. Если да, то может случиться так, что work.js запускается даже до jQuery (или других библиотек, которые я могу добавить в будущем).
На самом деле это не должно вызывать беспокойства: вы ставите сценарии в очередь для выполнения в определенном контексте JS, и в этом контексте не может быть состояния гонки, поскольку он однопоточный.
Тем не менее, правильный способ устранить эту проблему - объединить вызовы в цепочку:
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'
});
});
});
Или обобщенно:
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);
Или обещали (и привели больше в соответствие с правильной подписью):
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)
);
Или, черт возьми, нет, async
/await
-ед для еще более четкого синтаксиса:
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);
}
Обратите внимание, в Firefox вы можете просто использовать browser.tabs.executeScript
как он вернет обещание.
Помимо уже упомянутых решений, вы также можете скачать jquery.min.js
локально, а затем использовать его -
Для скачивания -
wget "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"
manifest.json -
"content_scripts": [
{
"js": ["/path/to/jquery.min.js", ...]
}
],
в HTML -
<script src="/path/to/jquery.min.js"></script>
Ссылка - https://developer.chrome.com/extensions/contentSecurityPolicy
Начиная с манифеста 3, анонимные функции не разрешены (ни в фоновом режиме). Файл Jquery.js обычно имеет анонимные функции. Вы должны задать им имя.
В моем случае я получил рабочее решение через Cross-Document Messaging (XDM) и Executing Chrome extension onclick вместо загрузки страницы.
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!')
}
}
);
Я загрузил jquery вручную и импортировал его в файл манифеста, как файл javascript.
maifest.json
"content_scripts": [
{
"matches": [...],
"js": ["jquery-3.6.0.min.js", ...],
}
]
folder sructure
extension
│ manifest.json
│ jquery-3.6.0.min.js
| ...