¿Cómo importo scripts a un trabajador de servicio usando la versión 3 del manifiesto de extensión de Chrome?

Resuelto bhanu asked hace 3 años • 0 respuestas

Estoy intentando migrar mi extensión de Chrome de la versión 2 del manifiesto a la 3. Ahora que los scripts en segundo plano son reemplazados por trabajadores de servicio en el manifiesto v3, ya no puedo usar un archivo html ni hacer referencia a jsarchivos en etiquetas de script.

¿ Hay alguna forma de importar mis archivos de script individuales al service_worker.jsarchivo?

Busqué casi todo en Internet y no encontré ninguna solución. Incluso los documentos oficiales aquí Registrar scripts en segundo plano no fueron tan útiles. Cualquier ayuda sería apreciada.

bhanu avatar Feb 28 '21 14:02 bhanu
Aceptado

En primer lugar, advertencias importantes:

  • Advertencia: Chrome 92 o versiones anteriores no muestran los errores ocurridos en el trabajador del servicio; fue un error , corregido en la versión más reciente de Chrome, que ahora muestra los errores en chrome://extensionsla página. Estas versiones antiguas de Chrome no pueden registrar el script en segundo plano si se produce una excepción no controlada durante su compilación (un error de sintaxis como un paréntesis sin cerrar) o la inicialización (por ejemplo, al acceder a una variable no definida), por lo que si aún admite el antiguo Chrome, es posible que desee envuelva el código en try/catch.

  • Advertencia: Chrome 92 o versiones anteriores requieren que el archivo de trabajo esté en la ruta raíz ( error ).

  • ¡Advertencia! No importe bibliotecas basadas en DOM como jQuery o axios porque los trabajadores del servicio no tienen DOM, por lo que no hay document, XMLHttpRequestetc. Úselo fetchdirectamente o busque/escriba una biblioteca que se base en fetcho no use windowo document.

0. Paquetes NPM

Utilice un paquete como webpack.

1. Módulos ES en Chrome 92 y posteriores

Habilitado agregando "type": "module"a la declaración de backgroundmanifest.json.

  • El nombre debe comenzar con una ruta y terminar con una extensión como .js o .mjs.
  • importSe puede utilizar una declaración estática .
  • La dinámica import()aún no está implementada ( crbug/1198822 ).

manifiesto.json:

"background": { "service_worker": "bg.js", "type": "module" },
"minimum_chrome_version": "92",

bg.js:

import {foo} from '/path/file.js';
import './file2.js';

Como se señaló al comienzo de esta respuesta, si todavía apunta a Chrome 92 o anterior, que no muestra los errores durante el registro, cada módulo importado también debe usar try/catch dentro donde sea posible una excepción.

2. importar scripts

Esta función incorporada recupera y ejecuta sincrónicamente los scripts para que sus variables y funciones globales estén disponibles de inmediato.

manifiesto.json:

"background": { "service_worker": "bg-loader.js" },

bg-loader.js es solo un contenedor try/catch para el código real en archivos separados:

try {
  importScripts('/path/file.js', '/path2/file2.js' /*, and so on */);
} catch (e) {
  console.error(e);
}

Si algún archivo arroja un error, no se importarán archivos posteriores. Si desea ignorar dichos errores y continuar importando, importe este archivo por separado en su propio bloque try-catch.

No olvide especificar una extensión de archivo, normalmente .jso .mjs.

2b. importScripts dentro de un oyente

Según la especificación, debemos usar un installevento de trabajador de servicio e importar todos los scripts que queremos poder importar en un evento asincrónico más adelante (técnicamente hablando, cualquier cosa fuera de la tarea inicial del bucle de eventos JS ). Este controlador se llama solo cuando la extensión está instalada o actualizada o cuando se vuelve a cargar una extensión descomprimida (porque equivale a una actualización).

Es así de complicado en MV3 porque los trabajadores de servicios fueron diseñados para la Web, donde los scripts remotos pueden no estar disponibles sin conexión. Con suerte, se simplificará en crbug/1198822 .

Ver también: complemento webpack-target-webextension para WebPack.

const importedScripts = [];

function tryImport(...fileNames) {
  try {
    const toRun = new Set(fileNames.filter(f => !importedScripts.includes(f)));
    if (toRun.size) {
      importedScripts.push(...toRun);
      importScripts(...toRun);
    }
    return true;
  } catch (e) {
    console.error(e);
  }
}

self.oninstall = () => {
  // The imported script shouldn't do anything, but only declare a global function
  // (someComplexScriptAsyncHandler) or use an analog of require() to register a module
  tryImport('/js/some-complex-script.js');
};

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.action === 'somethingComplex') {
    if (tryImport('/js/some-complex-script.js')) {
      // calling a global function from some-complex-script.js
      someComplexScriptAsyncHandler(msg, sender, sendResponse);
      return true;
    }
  }
});
wOxxOm avatar Feb 28 '2021 11:02 wOxxOm