Hoe jQuery te gebruiken in de Chrome-extensie?

Ik schrijf een Chrome-extensie. En ik wil jQuerygebruiken in mijn extensie. Ik gebruik geen achtergrondop de achtergrond, alleen een scriptop de achtergrond.

Hier zijn mijn bestanden:

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

Mijn background.js-bestand voert gewoon een ander bestand uit met de naam work.js

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

De belangrijkste logica van mijn extensie zit in work.js. De inhoud waarvan ik denk dat het hier niet van belang is voor deze vraag.

Wat ik wil vragen is hoe ik jQuery in mijn extensie kan gebruiken. Aangezien ik geen achtergrondpagina gebruik. Ik kan er niet zomaar jQuery aan toevoegen. Dus hoe kan ik jQuery toevoegen en gebruiken in mijn extensie?

Ik heb geprobeerd jQuery samen met mijn work.js uit het bestand background.jsuit te voeren.

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

En het werkt prima, maar ik heb het bezorgdheid of de scripts die op deze manier worden toegevoegd asynchroon worden uitgevoerd. Zo ja, dan kan het gebeuren dat Work.js zelfs vóór jQuery (of andere bibliotheken die ik in de toekomst kan toevoegen).

En ik zou ook willen weten wat de juiste en beste manier is om bibliotheken van derden te gebruiken, in mijn verchroomde extensie.


Antwoord 1, Autoriteit 100%

U moet uw jQuery-script toevoegen aan uw Chrome-uitbreidingsproject en op de backgroundsectie van uw manifest.json zoals deze:

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

Als u jQuery in een content_scripts nodig hebt, moet u deze ook in het manifest toevoegen:

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

Dit is wat ik deed.

Ook, als ik me op de juiste manier herinner, worden de achtergrondcripts uitgevoerd in een achtergrondvenster dat u via chrome://extensionskunt openen.


Antwoord 2, Autoriteit 17%

het is heel eenvoudig, gewoon het volgende:

Voeg de volgende regel toe in uw manifest.json

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

Nu bent u vrij om JQuery rechtstreeks uit URL

te laden

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

Bron: google-document


Antwoord 3, autoriteit 12%

En het werkt prima, maar ik maak me zorgen of de scripts die zijn toegevoegd om op deze manier te worden uitgevoerd, asynchroon worden uitgevoerd. Zo ja, dan kan het gebeuren dat work.js zelfs vóór jQuery draait (of andere bibliotheken die ik in de toekomst kan toevoegen).

Dat zou eigenlijk geen probleem moeten zijn: je zet scripts in de wachtrij om te worden uitgevoerd in een bepaalde JS-context, en die context kan geen race-conditie hebben omdat het single-threaded is.

De juiste manier om dit probleem weg te nemen, is door de oproepen aan elkaar te koppelen:

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

Of, algemeen:

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

of, bevorderde (en bracht meer in overeenstemming met de juiste handtekening):

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

Of, waarom de HECK NIET, async/ await-ED voor zelfs duidelijkere syntaxis:

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

Opmerking, in Firefox kunt u gewoon browser.tabs.executeScriptzoals het een belofte retourneert.


Antwoord 4, Autoriteit 10%

Afgezien van de reeds vermelde oplossingen, kunt u ook jquery.min.jslokaal downloaden en vervolgens gebruiken –

Om te downloaden –

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>

Referentie – https://developer.chrome.com/extensions/contentSecurityPolicy


Antwoord 5

In mijn geval kreeg ik een werkende oplossing via Cross-document Messaging (XDM)
en het uitvoeren van de Chrome-extensie onclick in plaats van het laden van de pagina.

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

mijnscript.js

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        if (request.message === "clicked_browser_action") {
        console.log('Hello world!')
        }
    }
);

Other episodes