¿Cómo usar jQuery en la extensión de Chrome?

128

Estoy escribiendo una extensión de Chrome. Y quiero usar jQueryen mi extensión. No estoy usando ninguna página de fondo , solo un script de fondo .

Aquí están mis archivos:

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

Mi background.jsarchivo solo ejecuta otro archivo llamadowork.js

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

La lógica principal de mi extensión está dentro work.js. El contenido del cual no creo importa aquí para esta pregunta.

Lo que quiero preguntar es cómo puedo usar jQuery en mi extensión. Como no estoy usando ninguna página de fondo. No puedo simplemente agregarle jQuery. Entonces, ¿cómo puedo agregar y usar jQuery en mi extensión?

Intenté ejecutar jQuery junto con mi work.js desde el background.jsarchivo.

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

Y funciona bien, pero me preocupa si los scripts agregados para ejecutarse de esta manera se ejecutan de forma asincrónica. En caso afirmativo, puede suceder que work.js se ejecute incluso antes jQuery (u otras bibliotecas que pueda agregar en el futuro).

Y también me gustaría saber cuál es la forma correcta y mejor de usar bibliotecas de terceros, en mi extensión de Chrome.

Ishan
fuente
2
¡La forma correcta es ir a la vainilla!
bjb568
Si está buscando cómo agregar jQuery a una extensión emergente (como lo estaba yo), vea esta pregunta: stackoverflow.com/questions/12035242/…
Pro Q

Respuestas:

124

Debe agregar su script jquery a su proyecto de extensión de Chrome y a la backgroundsección de su manifest.json de esta manera:

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

Si necesita jquery en un content_scripts, también debe agregarlo en el manifiesto:

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

Esto es lo que hice.

Además, si recuerdo correctamente, los scripts de fondo se ejecutan en una ventana de fondo que puede abrir a través de chrome://extensions.

Nico
fuente
77
¿A qué te refieres exactamente You have to add your jquery script to your chrome-extension project? Hice esto: manifest.json: "background": { `" scripts ": [" thirdParty / jquery-2.0.3.js "," background.js "],` `" persistent ": false``}, `y descargué el jQuery a la carpeta de la tercera parte. Sin embargo, todavía no puedo usar jQuery. Da el error: Uncaught ReferenceError: $ is not defined agregué esto a mi work.jsarchivo para probarlo. $("body").html("Foo!");
Ishan
El comentario anterior parece un desastre, pero al agregar comentarios, no se muestra la vista previa. Por favor perdóname por eso.
Ishan
Me refiero a agregarlo a su carpeta de extensión de Chrome. Como /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. Deberías hacer lo mismo con tu trabajo.js.
Nico
1
Intenté hacer lo que dijiste. Pero sigo recibiendo el mismo error de no poder acceder a jquery desde mi work.jsarchivo. Uncaught ReferenceError: $ is not defined. Si puede, ¿puede cargar un ejemplo de trabajo en alguna parte? Solo un ejemplo simple como hacer '$ ("body"). Html ("Foo!");' en work.js.
Ishan
77
También tuve problemas para obtener jQueryo $ser reconocido. Resultó que estaba haciendo referencia a jQuery por última vez en la matriz de manifiesto. Cuando lo puse primero fue reconocido.
BenR
18

Es muy fácil, solo haz lo siguiente:

agregue la siguiente línea en su manifest.json

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

Ahora puede cargar jQuery directamente desde url

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

Fuente: google doc

Vikas Bansal
fuente
1
¿Qué pasa si tiene varios scripts para cargar?
otro
1
Excelente respuesta si desea cargar su script desde un servidor remoto (lo que efectivamente requiere que confíe en el servidor remoto con su extensión y todo lo que tiene acceso).
Nathaniel Verhaaren 01 de
1
@NathanielVerhaaren Este es un punto razonable para plantear, pero puede mitigarse verificando la fuente usando subresource integrity(SRI).
Dan Atkinson
13

Y funciona bien, pero me preocupa si los scripts agregados para ejecutarse de esta manera se ejecutan de forma asincrónica. En caso afirmativo, puede suceder que work.js se ejecute incluso antes de jQuery (u otras bibliotecas que pueda agregar en el futuro).

Eso no debería ser realmente una preocupación: puede poner en cola los scripts para que se ejecuten en un determinado contexto JS, y ese contexto no puede tener una condición de carrera ya que es de un solo subproceso.

Sin embargo, la forma correcta de eliminar esta preocupación es encadenar las llamadas:

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

O, generalizado:

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

O, prometido (y traído más en línea con la firma adecuada):

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

O, por qué no, async/ await-ed para una sintaxis aún más clara:

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

Tenga en cuenta que en Firefox puede usarlo browser.tabs.executeScriptya que devolverá una Promesa.

Xan
fuente
El primer método es brillante. Como alguien que no conoce mucho JavaScript, nunca consideré algo así.
FriskySaga
11

Además de las soluciones ya mencionadas, también puede descargar jquery.min.jslocalmente y luego usarlo:

Para descargar -

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>

Referencia: https://developer.chrome.com/extensions/contentSecurityPolicy

Arik Pamnani
fuente
3
Esta es la mejor manera ... No necesita la parte html.
c-an
1

En mi caso, obtuve una solución de trabajo a través de la mensajería entre documentos (XDM) y la ejecución de la extensión de Chrome al hacer clic en lugar de cargar la página.

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
fuente