Jak korzystać z jQuery w rozszerzeniu Chrome?


128

Piszę rozszerzenie do Chrome. I chcę użyć jQueryw moim rozszerzeniu. Nie używam żadnej strony w tle , tylko skrypt działający w tle .

Oto moje pliki:

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"
    }
}

Mój background.jsplik po prostu uruchamia inny plik o nazwiework.js

// Respond to the click on extension Icon
chrome.browserAction.onClicked.addListener(function (tab) {
    chrome.tabs.executeScript({
        file: 'work.js'
    });
});

Główna logika mojego rozszerzenia znajduje się wewnątrz work.js. Treść, która moim zdaniem nie ma tutaj znaczenia dla tego pytania.

Chcę zapytać, jak mogę używać jQuery w moim rozszerzeniu. Ponieważ nie używam żadnej strony w tle. Nie mogę po prostu dodać do niego jQuery. Jak więc mogę dodać i używać jQuery do mojego rozszerzenia?

Próbowałem uruchomić jQuery wraz z moim plikiem work.js z background.jspliku.

// 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'
    });
});

I działa dobrze, ale mam obawy, czy skrypty dodane do wykonania w ten sposób są wykonywane asynchronicznie. Jeśli tak, może się zdarzyć, że plik work.js działa jeszcze przed jQuery (lub innymi bibliotekami, które mogę dodać w przyszłości).

Chciałbym też wiedzieć, jaki jest właściwy i najlepszy sposób korzystania z bibliotek innych firm w moim rozszerzeniu do Chrome.


2
Właściwy sposób to przejść do wanilii!
— bjb568,

Jeśli szukasz tutaj, jak dodać jQuery do wyskakującego rozszerzenia (tak jak ja), zobacz to pytanie: stackoverflow.com/questions/12035242/ ...
— Pro Q

Odpowiedzi:


124

Musisz dodać skrypt jquery do projektu rozszerzenia chrome i do backgroundsekcji pliku manifest.json w następujący sposób:

  "background":
    {
        "scripts": ["thirdParty/jquery-2.0.3.js", "background.js"]
    }

Jeśli potrzebujesz jquery w content_scripts, musisz dodać go również do manifestu:

"content_scripts": 
    [
        {
            "matches":["http://website*"],
            "js":["thirdParty/jquery.1.10.2.min.js", "script.js"],
            "css": ["css/style.css"],
            "run_at": "document_end"
        }
    ]

To właśnie zrobiłem.

Ponadto, jeśli dobrze pamiętam, skrypty działające w tle są wykonywane w oknie w tle, które można otworzyć za pomocą chrome://extensions.


7
Co dokładnie masz na myśli You have to add your jquery script to your chrome-extension project? Zrobiłem to: manifest.json: "background": { `" scripts ": [" thirdParty / jquery-2.0.3.js "," background.js "],` `" persistent ": false``}, `i pobrałem jQuery do folderu ThirdParty. Jednak nadal nie mogę używać jQuery. Daje błąd: Uncaught ReferenceError: $ is not defined dodałem to do mojego work.jspliku w celu przetestowania. $("body").html("Foo!");
— Ishan

Powyższy komentarz wygląda jak bałagan, ale podczas dodawania komentarzy podgląd nie jest wyświetlany. Proszę, wybacz mi to.
— Ishan,

Mam na myśli dodanie go do twojego folderu rozszerzenia chrome. Polub /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. Powinieneś zrobić to samo z plikiem work.js.
— Nico

1
Próbowałem zrobić to, co powiedziałeś. Ale nadal pojawia się ten sam błąd, że nie mogę uzyskać dostępu do jquery z mojego work.jspliku. Uncaught ReferenceError: $ is not defined. Jeśli możesz, czy możesz przesłać gdzieś działający przykład. Wystarczy prosty przykład, jak wykonanie '$ ("body"). Html ("Foo!");' w work.js.
— Ishan

7
Miałem też problem z dostaniem się jQuerylub byciem $rozpoznanym. Okazało się, że odwoływałem się do jQuery jako ostatnie w tablicy manifestu. Kiedy umieściłem to jako pierwsze, zostało rozpoznane.
— BenR

18

Jest to bardzo łatwe, wystarczy wykonać następujące czynności:

dodaj następujący wiersz do swojego manifest.json

"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",

Teraz możesz ładować jQuery bezpośrednio z adresu URL

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

Źródło: dokument google


1
Co jeśli masz wiele skryptów do załadowania?
— kolejny

1
Świetna odpowiedź, jeśli chcesz załadować swój skrypt ze zdalnego serwera (co w praktyce wymaga, abyś ufał zdalnemu serwerowi ze swoim rozszerzeniem i wszystkim, do czego ma dostęp).
— Nathaniel Verhaaren

1
@NathanielVerhaaren Jest to rozsądna kwestia do podniesienia, ale można ją złagodzić, weryfikując źródło za pomocą subresource integrity(SRI).
— Dan Atkinson

13

I działa dobrze, ale mam obawy, czy skrypty dodane do wykonania w ten sposób są wykonywane asynchronicznie. Jeśli tak, może się zdarzyć, że plik work.js działa jeszcze przed jQuery (lub innymi bibliotekami, które mogę dodać w przyszłości).

To naprawdę nie powinno być problemem: kolejkujesz skrypty do wykonania w określonym kontekście JS, a ten kontekst nie może mieć warunku wyścigu, ponieważ jest jednowątkowy.

Jednak właściwym sposobem na wyeliminowanie tego problemu jest łańcuchowanie połączeń:

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'
        });
    });
});

Lub uogólnione:

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);

Lub obiecał (i bardziej zgodny z odpowiednim podpisem):

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)
);

Lub, do cholery, async/ await-ed dla jeszcze jaśniejszej składni:

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);
}

Uwaga, w Firefoksie możesz po prostu użyć, browser.tabs.executeScriptponieważ zwróci Obietnicę.


Pierwsza metoda jest genialna. Jako ktoś, kto nie zna zbyt wiele JavaScript, nigdy nie rozważałem czegoś takiego.
— FriskySaga

11

Oprócz wspomnianych już rozwiązań możesz również pobrać jquery.min.jslokalnie, a następnie z niego korzystać -

Do pobrania -

wget "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"

manifest.json -

"content_scripts": [
   {
    "js": ["/path/to/jquery.min.js", ...]
   }
],

w html -

<script src="/path/to/jquery.min.js"></script>

Odniesienie - https://developer.chrome.com/extensions/contentSecurityPolicy


3
To najlepszy sposób ... Nie potrzebujesz części html.
— c-an

1

W moim przypadku dostałem działające rozwiązanie poprzez Cross-document Messaging (XDM) i uruchamianie rozszerzenia Chrome onclick zamiast ładowania strony.

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!')
        }
    }
);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.