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.

Ishan
źródło
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.

Nico
źródło
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

Vikas Bansal
źródło
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ę.

Xan
źródło
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

Arik Pamnani
źródło
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!')
        }
    }
);
Rusłana Nowikowa
źródło