Как использовать jQuery в расширении Chrome?

129

Пишу расширение для хрома. И я хочу использовать 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.

Ishan
источник
2
Правильный способ - отказаться от ванили!
bjb568
Если вы здесь ищете, как добавить jQuery во всплывающее расширение (как и я), см. Этот вопрос: stackoverflow.com/questions/12035242/…
Pro Q

Ответы:

125

Вам нужно добавить свой jquery-скрипт в свой проект расширения chrome и в 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.

Нико
источник
7
Что вы имеете в виду You have to add your jquery script to your chrome-extension project? Я сделал это: manifest.json: "background": { `" scripts ": [" thirdParty / jquery-2.0.3.js "," background.js "],` `" persistent ": false``}, и я загрузил jQuery в папку ThirdParty. Однако я все еще не могу использовать jQuery. Это дает ошибку: Uncaught ReferenceError: $ is not defined я добавил это в свой work.jsфайл для тестирования. $("body").html("Foo!");
Ishan
Приведенный выше комментарий выглядит беспорядочно, но при добавлении комментариев предварительный просмотр не отображается. Пожалуйста, простите меня за это.
Ishan
Я хочу добавить его в папку с расширением Chrome. Например, /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. Вы должны сделать то же самое со своим work.js.
Нико
1
Я пытался сделать то, что ты сказал. Но я все еще получаю ту же ошибку, что не могу получить доступ к jquery из моего work.jsфайла. Uncaught ReferenceError: $ is not defined, Если можете, не могли бы вы выложить где-нибудь рабочий пример. Просто простой пример, например, "$ (" body "). Html (" Foo! "); ' в work.js.
Ishan
7
У меня также были проблемы с получением jQueryили $быть признанным. Оказалось, что я ссылался на jQuery последним в массиве манифеста. Когда я поставил его первым, он был признан.
BenR
18

Это очень просто, просто сделайте следующее:

добавьте следующую строку в свой manifest.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

Викас Бансал
источник
1
Что делать, если вам нужно загрузить несколько скриптов?
еще один
1
Отличный ответ, если вы хотите загрузить свой скрипт с удаленного сервера (что фактически требует, чтобы вы доверяли удаленному серверу свое расширение и все, к чему у него есть доступ).
Натаниэль Верхарен 01
1
@NathanielVerhaaren Это разумный вопрос, который стоит поднять, но его можно смягчить, проверив источник с помощью subresource integrity(SRI).
Дэн Аткинсон
13

И он работает нормально, но меня беспокоит, выполняются ли скрипты, добавленные для выполнения таким образом, асинхронно. Если да, то может случиться так, что 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-ed для еще более ясного синтаксиса:

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поскольку он вернет Promise.

Xan
источник
Первый метод великолепен. Как человек, не очень разбирающийся в JavaScript, я никогда не думал об этом.
FriskySaga
11

Помимо уже упомянутых решений, вы также можете загрузить его 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
Это лучший способ ... HTML-часть не нужна.
c-an
1

В моем случае я получил рабочее решение через 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!')
        }
    }
);
Руслан Новиков
источник