Comment utiliser jQuery dans l'extension Chrome?

129

J'écris une extension chrome. Et je veux utiliser jQuerydans mon extension. Je n'utilise aucune page de fond , juste un script de fond .

Voici mes fichiers:

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

Mon background.jsfichier exécute juste un autre fichier nomméwork.js

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

La logique principale de mon extension est à l'intérieur work.js. Le contenu dont je ne pense pas qu'il importe ici pour cette question.

Ce que je veux demander, c'est comment puis-je utiliser jQuery dans mon extension. Puisque je n'utilise aucune page de fond. Je ne peux pas simplement y ajouter jQuery. Alors, comment puis-je ajouter et utiliser jQuery dans mon extension?

J'ai essayé d'exécuter jQuery avec mon work.js à partir d'un background.jsfichier.

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

Et cela fonctionne bien, mais j'ai le souci de savoir si les scripts ajoutés pour être exécutés de cette manière sont exécutés de manière asynchrone. Si oui, il peut arriver que work.js s'exécute avant même jQuery (ou d'autres bibliothèques que je pourrais ajouter à l'avenir).

Et j'aimerais également savoir quelle est la manière correcte et la meilleure d'utiliser des bibliothèques tierces, dans mon extension chrome.

Ishan
la source
2
La bonne façon est d'aller à la vanille!
bjb568
Si vous cherchez ici comment ajouter jQuery à une extension pop-up (comme je l'étais), consultez cette question: stackoverflow.com/questions/12035242/...
Pro Q

Réponses:

125

Vous devez ajouter votre script jquery à votre projet d'extension chrome et à la backgroundsection de votre manifest.json comme ceci:

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

Si vous avez besoin de jquery dans un content_scripts, vous devez également l'ajouter dans le manifeste:

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

C'est ce que j'ai fait.

De plus, si je me souviens bien, les scripts d'arrière-plan sont exécutés dans une fenêtre d'arrière-plan que vous pouvez ouvrir via chrome://extensions.

Nico
la source
7
Eh bien, que voulez-vous dire exactement You have to add your jquery script to your chrome-extension project? J'ai fait ceci: manifest.json: "background": { `" scripts ": [" thirdParty / jquery-2.0.3.js "," background.js "],` `" persistent ": false``}, `et j'ai téléchargé le jQuery dans le dossier ThirdParty. Cependant, je ne peux toujours pas utiliser jQuery. Cela donne l'erreur: Uncaught ReferenceError: $ is not defined j'ai ajouté ceci à mon work.jsfichier pour le test. $("body").html("Foo!");
Ishan
Le commentaire ci-dessus ressemble à un désordre, mais lors de l'ajout de commentaires, l'aperçu n'est pas affiché. Veuillez me pardonner.
Ishan
Je veux l'ajouter à votre dossier d'extension chrome. Comme /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. Vous devriez faire la même chose avec votre work.js.
Nico
1
J'ai essayé de faire ce que tu as dit. Mais j'obtiens toujours la même erreur de ne pas pouvoir accéder à jquery à partir de mon work.jsfichier. Uncaught ReferenceError: $ is not defined. Si vous le pouvez, pouvez-vous s'il vous plaît télécharger un exemple de travail quelque part. Juste un exemple simple comme faire '$ ("body"). Html ("Foo!");' dans work.js.
Ishan
7
J'ai également eu du mal à être reconnu jQueryou $reconnu. Il s'est avéré que je faisais référence à jQuery en dernier dans le tableau du manifeste. Quand je l'ai mis en premier, il a été reconnu.
BenR
18

C'est très simple de faire ce qui suit:

ajoutez la ligne suivante dans votre manifest.json

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

Vous êtes maintenant libre de charger jQuery directement à partir de l'URL

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

Source: doc google

Vikas Bansal
la source
1
Et si vous avez plusieurs scripts à charger?
un autre
1
Excellente réponse si vous souhaitez charger votre script à partir d'un serveur distant (ce qui nécessite effectivement que vous fassiez confiance au serveur distant avec votre extension et tout ce à quoi il a accès).
Nathaniel Verhaaren
1
@NathanielVerhaaren C'est un point raisonnable à soulever, mais il peut être atténué en vérifiant la source en utilisant subresource integrity(SRI).
Dan Atkinson
13

Et cela fonctionne bien, mais j'ai le souci de savoir si les scripts ajoutés pour être exécutés de cette manière sont exécutés de manière asynchrone. Si oui, il peut arriver que work.js s'exécute avant même jQuery (ou d'autres bibliothèques que je pourrais ajouter à l'avenir).

Cela ne devrait pas vraiment être un problème: vous mettez en file d'attente des scripts à exécuter dans un certain contexte JS, et ce contexte ne peut pas avoir de condition de concurrence car il est mono-thread.

Cependant, la bonne façon d'éliminer ce problème est d'enchaîner les appels:

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

Ou, généralisé:

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

Ou, promis (et mis plus en ligne avec la signature appropriée):

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

Ou, pourquoi diable pas, async/ await-ed pour une syntaxe encore plus claire:

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

Notez que dans Firefox, vous pouvez simplement l'utiliser browser.tabs.executeScriptcar il renverra une promesse.

Xan
la source
La première méthode est géniale. En tant que personne qui ne connaît pas beaucoup JavaScript, je n'ai jamais envisagé quelque chose comme ça.
FriskySaga
11

Outre les solutions déjà mentionnées, vous pouvez également télécharger jquery.min.jslocalement puis l'utiliser -

Pour le téléchargement -

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

manifest.json -

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

en html -

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

Référence - https://developer.chrome.com/extensions/contentSecurityPolicy

Arik Pamnani
la source
3
C'est la meilleure façon ... Vous n'avez pas besoin de la partie html.
c-an
1

Dans mon cas, j'ai obtenu une solution de travail via la messagerie croisée (XDM) et l'exécution de l'extension Chrome en cliquant au lieu du chargement de la page.

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
la source