Wie verwende ich jQuery in der Chrome-Erweiterung?

128

Ich schreibe eine Chrome-Erweiterung. Und ich möchte jQueryin meiner Erweiterung verwenden. Ich benutze keine Hintergrundseite , nur ein Hintergrundskript .

Hier sind meine Dateien:

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

In meiner background.jsDatei wird nur eine andere Datei mit dem Namen ausgeführtwork.js

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

Die Hauptlogik meiner Erweiterung liegt im Inneren work.js. Der Inhalt, von dem ich denke, dass er hier für diese Frage nicht wichtig ist.

Ich möchte fragen, wie ich jQuery in meiner Erweiterung verwenden kann. Da ich keine Hintergrundseite benutze. Ich kann nicht einfach jQuery hinzufügen. Wie kann ich jQuery zu meiner Erweiterung hinzufügen und verwenden?

Ich habe versucht, jQuery zusammen mit meiner work.js aus der background.jsDatei auszuführen .

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

Und es funktioniert gut, aber ich habe Bedenken, ob die auf diese Weise hinzugefügten Skripte asynchron ausgeführt werden. Wenn ja, kann es vorkommen, dass work.js bereits vor jQuery (oder anderen Bibliotheken, die ich möglicherweise in Zukunft hinzufügen werde) ausgeführt wird.

Außerdem möchte ich wissen, wie Bibliotheken von Drittanbietern in meiner Chrome-Erweiterung richtig und am besten verwendet werden können.

Ishan
quelle
2
Der richtige Weg ist Vanille zu gehen!
bjb568
Wenn Sie hier nach Informationen
Pro Q

Antworten:

124

Sie müssen Ihr jquery-Skript wie folgt zu Ihrem Chrome-Erweiterungsprojekt und zum backgroundAbschnitt Ihrer manifest.json hinzufügen :

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

Wenn Sie jquery in einem content_scripts benötigen, müssen Sie es auch im Manifest hinzufügen:

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

Das habe ich getan.

Wenn ich mich richtig erinnere, werden die Hintergrundskripte in einem Hintergrundfenster ausgeführt, über das Sie öffnen können chrome://extensions.

Nico
quelle
7
Was meinst du genau damit You have to add your jquery script to your chrome-extension project? Ich habe dies getan: manifest.json: "background": { `" scripts ": [" ThirdParty / jquery-2.0.3.js "," background.js "],` `" persistent ": false``}, `und ich habe das heruntergeladen jQuery zum Ordner ThirdParty. Ich kann jQuery jedoch immer noch nicht verwenden. Es gibt den Fehler: Uncaught ReferenceError: $ is not defined Ich habe dies zu work.jsTestzwecken zu meiner Datei hinzugefügt . $("body").html("Foo!");
Ishan
Der obige Kommentar sieht wie ein Durcheinander aus, aber beim Hinzufügen von Kommentaren wird keine Vorschau angezeigt. Bitte vergib mir das.
Ishan
Ich möchte es Ihrem Chrome-Erweiterungsordner hinzufügen. Wie /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. Sie sollten dasselbe mit Ihrer work.js tun.
Nico
1
Ich habe versucht, das zu tun, was du gesagt hast. Aber ich erhalte immer noch den gleichen Fehler, dass ich nicht über meine work.jsDatei auf jquery zugreifen kann. Uncaught ReferenceError: $ is not defined. Wenn Sie können, können Sie bitte irgendwo ein funktionierendes Beispiel hochladen. Nur ein einfaches Beispiel wie '$ ("body"). Html ("Foo!");' in work.js.
Ishan
7
Ich hatte auch Schwierigkeiten zu geraten jQueryoder $erkannt zu werden. Es stellte sich heraus, dass ich zuletzt im Manifest-Array auf jQuery verwies. Als ich es zuerst stellte, wurde es erkannt.
BenR
18

Es ist sehr einfach, einfach Folgendes zu tun:

Fügen Sie die folgende Zeile in Ihre manifest.json ein

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

Jetzt können Sie jQuery direkt von der URL laden

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

Quelle: Google Doc

Vikas Bansal
quelle
1
Was ist, wenn Sie mehrere Skripte laden müssen?
weiterer
1
Gute Antwort, wenn Sie Ihr Skript von einem Remote-Server laden möchten (was effektiv erfordert, dass Sie dem Remote-Server Ihre Erweiterung und alles, worauf er Zugriff hat, anvertrauen).
Nathaniel Verhaaren
1
@NathanielVerhaaren Dies ist ein vernünftiger Punkt, der angesprochen werden kann. Er kann jedoch durch Überprüfen der Quelle mithilfe von subresource integrity(SRI) gemildert werden .
Dan Atkinson
13

Und es funktioniert gut, aber ich habe Bedenken, ob die auf diese Weise hinzugefügten Skripte asynchron ausgeführt werden. Wenn ja, kann es vorkommen, dass work.js bereits vor jQuery (oder anderen Bibliotheken, die ich möglicherweise in Zukunft hinzufügen werde) ausgeführt wird.

Das sollte eigentlich kein Problem sein: Sie stellen Skripte in die Warteschlange, die in einem bestimmten JS-Kontext ausgeführt werden sollen, und dieser Kontext kann keine Race-Bedingung haben, da er Single-Threaded ist.

Der richtige Weg, um dieses Problem zu beseitigen, besteht darin, die Anrufe zu verketten:

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

Oder verallgemeinert:

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

Oder versprochen (und mehr mit der richtigen Unterschrift in Einklang gebracht):

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

Oder warum zum Teufel nicht, async/ await-ed für noch klarere 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);
}

Beachten Sie, dass Sie in Firefox nur verwenden können, browser.tabs.executeScriptda es ein Versprechen zurückgibt.

Xan
quelle
Die erste Methode ist brillant. Als jemand, der nicht viel JavaScript kennt, habe ich so etwas nie in Betracht gezogen.
FriskySaga
11

Neben den bereits erwähnten Lösungen können Sie diese auch jquery.min.jslokal herunterladen und dann verwenden -

Zum Herunterladen -

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>

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

Arik Pamnani
quelle
3
Dies ist der beste Weg ... Sie brauchen den HTML-Teil nicht.
c-an
1

In meinem Fall habe ich eine funktionierende Lösung durch Cross-Document Messaging (XDM) und Ausführen der Chrome-Erweiterung per Mausklick anstelle des Seitenladens erhalten.

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!')
        }
    }
);
Ruslan Novikov
quelle