Cómo Construir una Extensión de Chrome Usando React

Rate this content
Bookmark
Slides

El año pasado, como parte de mi trabajo en Bloomberg, se me asignó la tarea de construir una Extensión de Chrome, y convencí a mi equipo de permitirme construir la extensión en React en lugar de JavaScript básico. Esto tenía varias ventajas, como hacer que el código sea más mantenible y más fácil de entender, además de permitirnos usar una biblioteca de componentes preexistentes para un estilo consistente en toda la empresa, reduciendo la cantidad de código CSS que teníamos que escribir. En mi presentación, les mostraré una muestra de una Extensión de Chrome para uso personal que construí utilizando React y Material UI, que responde automáticamente a los correos electrónicos enviados en Gmail y te permite tomar notas sobre la conversación. También compartiré los pasos para construir tu propia Extensión de Chrome usando React, y las lecciones aprendidas en el proceso!

18 min
06 Jun, 2023

Video Summary and Transcription

Esta Charla trata sobre la construcción de una extensión de Chrome usando React. Cubre la configuración, permisos y comportamientos de la extensión, así como la llamada a servicios externos y la ejecución de la extensión localmente. La Charla también discute el proceso de publicación de la extensión e incluye una demostración de un sistema de gestión de correos electrónicos. En general, proporciona una descripción general completa de la construcción y implementación de una extensión de Chrome usando React.

Available in English

1. Introducción y Resumen

Short description:

Esta parte presenta al orador y el tema de la charla, que es construir una extensión de Chrome usando React. El orador comparte su experiencia y antecedentes, así como el propósito de la extensión que construyó. Menciona las características de la extensión y su plan de discutir los pasos para construir una extensión de Chrome usando React. También menciona brevemente las extensiones de Firefox y la compatibilidad entre ellas.

¡Hola a todos, y gracias por sintonizar! También quiero agradecer al comité de la conferencia por aceptar mi charla aquí. Mi charla trata sobre cómo construir una extensión de Chrome usando React.

Un poco sobre mí. Mi nombre es Adina. Soy una ingeniera de software full-stack en Bloomberg en el equipo de ingeniería de RRHH, donde me enfoco principalmente en elementos de front-end. Soy originaria de Rumania, pero he estado en Estados Unidos durante casi la mitad de mi vida. Actualmente vivo en la ciudad de Nueva York con mi esposo y mi perro, y el nombre de mi perro es Stacks y es importante porque estaremos respondiendo a algunos correos electrónicos que Stacks a menudo recibe en su bandeja de entrada y que él podría querer posponer.

El año pasado, como parte de mi trabajo en Bloomberg, se me encargó construir una extensión de Chrome. Decidimos construir la extensión en React en lugar de JavaScript básico, ya que eso haría que el código sea más comprensible y mantenible, así como más fácil de estilizar mediante el uso de componentes específicos de Bloomberg de React. En esta presentación, les mostraré una extensión de muestra que he llamado Email Postponer, que construí específicamente para demostrar aquí. Esta extensión responde automáticamente a los correos electrónicos enviados en Gmail según la entrada del usuario, y también permite a los usuarios agregar notas privadas a sus correos electrónicos. También compartiré los pasos para construir tu propia extensión de Chrome usando React y las lecciones aprendidas en el proceso. También mencionaré brevemente las extensiones de Firefox y la compatibilidad entre ambas.

2. Extension Overview and Setup

Short description:

Esta parte proporciona una descripción general de la extensión Email Postponer, incluyendo sus características y cómo interactúa con Chrome. Explica los pasos para configurar la extensión utilizando Create React app y TypeScript, así como el uso de la API de Chrome. La extensión utiliza un archivo manifest.json y sigue la versión 3 del manifiesto. También se discute el papel del service worker y los content scripts en la funcionalidad de la extensión. Los content scripts permiten la comunicación entre el código de React y el script de fondo, y la extensión está diseñada para abrirse como un panel lateral en Gmail. La sección concluye mencionando la necesidad de agregar recursos accesibles desde la web a la extensión.

Para la agenda, comenzaré dando una descripción general de la extensión que construí para demostrar aquí, luego explicaré los pasos para configurar una extensión en React, resaltando algunas capacidades interesantes que le di a la extensión Email Postponer, hablaré sobre cómo ejecutar la extensión localmente, así como publicarla en la tienda.

Luego, tocaré brevemente la compatibilidad entre navegadores y cómo convertir una extensión de Chrome en un complemento de Firefox. Y terminaré mostrando una demostración en video de la extensión Email Postponer en acción.

Entonces, para una descripción general, la extensión Email Postponer se ve como una página web, como se puede ver a la derecha, solo se abre en Gmail, se abre como un panel lateral en lugar de una ventana emergente, porque queremos poder seleccionar información en el sitio web sin que se cierre la ventana emergente, utiliza Material UI para facilitar el estilo de los componentes listos para usar que son consistentes con el diseño de Material de Google, permite a los usuarios interactuar con el contenido de la página web tanto de forma manual como automática, y se comunica con el servicio backend utilizando la API Fetch.

Para configurar la extensión, primero creé un nuevo proyecto utilizando Create React app en TypeScript. Luego tuve que cambiar el comando de compilación para que React genere archivos separados de JavaScript y HTML para evitar errores de política de seguridad de contenido. También configuré para que no genere mapas de origen para eliminar algunas advertencias adicionales. Debido a que estamos utilizando TypeScript, tuve que instalar algunos tipos adicionales para usar la API de Chrome. El proyecto utiliza la API de Chrome para interactuar con Chrome mediante el uso de un objeto inyectado que también se llama Chrome. Create React app crea un archivo manifest.json para nosotros, pero las extensiones requieren una estructura específica para eso. Cada extensión debe tener un archivo manifest.json y debe tener el nombre manifest.json en su directorio raíz. Google está en proceso de eliminar la versión 2 del manifiesto, aunque acaban de anunciar algunos retrasos en esto en Google I/O. Sin embargo, estamos utilizando la versión 3 del manifiesto en nuestra extensión de Email Postponer. Debido a que queremos abrir la extensión como un panel lateral, queremos asegurarnos de que la acción esté vacía aquí. Nuestra extensión tomará su contexto de un archivo index.html que se compila a partir de React. El service worker, que también se conoce coloquialmente como un script de fondo, aunque hay algunas diferencias entre los dos, se ejecuta en todas las pestañas del navegador y se ejecuta al iniciar el navegador. Escucha eventos específicos en segundo plano, como cambiar de pestaña o actualizar URL. Toma acciones a nivel de navegador en consecuencia y se comunica con el código de la extensión y los content scripts a través del intercambio de mensajes. Este script es uno de los dos scripts escritos en JavaScript básico, y lo usamos para abrir y cerrar el panel lateral del sitio, así como para llamar al servicio res utilizando la API Fetch, ya que llamarlo desde React nos daría errores de intercambio de recursos entre orígenes.

Los content scripts son scripts que se ejecutan en el contexto de las páginas web y tienen acceso a elementos, objetos y métodos del DOM. Se ejecutan en instancias separadas en pestañas separadas, una instancia por pestaña, y se ejecutan en páginas que coinciden con la expresión regular de coincidencia, y se comunican con el service worker y el código de React a través del intercambio de mensajes. Los content scripts, de los cuales solo tenemos uno en esta extensión, también están escritos en JavaScript básico, y usamos el nuestro para crear un panel lateral, iframe, pasar mensajes entre el código de React y el script de fondo, así como copiar y pegar texto seleccionado en la extensión. Además, la extensión se abre solo en Gmail, ya que Gmail es la única expresión que coincide con la expresión regular en la propiedad matches.

Estas son algunas de las formas en que se pasan mensajes en las extensiones. Los content scripts se encuentran en el medio entre el código de React y el script de fondo. El código de React se comunica con los content scripts a través del intercambio de mensajes. Los content scripts toman acciones en la página web en la que se ejecuta la extensión o pasan mensajes al script de fondo, que luego puede tomar acciones a nivel de navegador en consecuencia. El script de fondo puede comunicarse directamente con el código de React, así como con los content scripts, también a través del intercambio de mensajes. Dado que estamos ejecutando la extensión en un panel lateral en lugar de una ventana emergente, debemos agregar recursos accesibles desde la web a la extensión.

3. Extension Permissions and Behaviors

Short description:

El código de la extensión se encuentra en el archivo index.html y los recursos están disponibles en todas las páginas web. Solo estamos utilizando el permiso de pestaña activa para abrir y cerrar un panel lateral. Los permisos de host otorgan a la extensión la capacidad de enviar solicitudes de recursos compartidos entre orígenes. Creamos un iframe en el script de contenido que se muestra y se oculta al recibir un mensaje de alternar extensión. Próximamente, las extensiones podrán utilizar el panel lateral en Chrome, lo que mejora significativamente los flujos de trabajo. Podemos copiar el texto seleccionado del navegador consultando la pestaña activa y utilizando el método getSelection del documento DOM. También podemos hacer clic automáticamente en botones del sitio web consultando la pestaña activa y utilizando el método DOMDocumentQuerySelector.

Y por defecto no hay ninguno. El código de la extensión se encuentra en el archivo index.html y los recursos están disponibles en todas las páginas web. La opción de permisos es similar a los permisos en su teléfono cuando instala una aplicación. Aquí solo estamos utilizando el permiso de pestaña activa, que otorga a la extensión acceso temporal a la pestaña activa actual. También necesitamos este permiso para abrir y cerrar un panel lateral.

Por último, los permisos de host otorgan a la extensión la capacidad de enviar solicitudes de recursos compartidos entre orígenes a los hosts mencionados en la matriz. Esto nos permite realizar las llamadas de servicio que nos permiten guardar nuestras notas. Normalmente, las extensiones se abren en una ventana emergente y se cierran cuando pierden el enfoque. Dado que nuestra extensión es un formulario que queremos completar utilizando texto del sitio web, necesitamos que se mantenga enfocada y activa. El primer paso fue asegurarse de que no haya una propiedad de ventana emergente predeterminada en el campo de acción del archivo manifest.json. Recuerde que estaba vacío en la diapositiva anterior. Luego, necesitamos un event listener en el service worker para cuando se hace clic en el icono de la extensión. Podemos llamar a esto alternar extensión. Esto envía un mensaje al script de contenido.

En el script de contenido, necesitamos crear un iframe que no se muestra, pero cuya fuente está index.html. Como puede ver aquí, tenemos un iframe y la fuente es index.html. Luego, necesitamos agregar un event listener que alterne entre mostrar y ocultar el iframe al recibir un mensaje de alternar extensión. Vale la pena mencionar que en la conferencia Google I/O hace unos días, el orador mencionó que las extensiones pronto podrán utilizar el panel lateral en Chrome. La API del panel lateral es una función futura de la versión tres del manifiesto que aún no está ampliamente disponible. Y se comportará de manera un poco diferente a lo que describí aquí. Pero mejorará significativamente los flujos de trabajo, al menos en Chrome.

Uno de los comportamientos que quiero destacar es copiar texto seleccionado en el navegador. Para copiar texto seleccionado del navegador, debemos consultar la pestaña activa actual en la ventana actual y enviar un mensaje al script de contenido. Cuando el script de contenido recibe el mensaje, simplemente utiliza el método getSelection del documento DOM para obtener el texto y luego lo envía de vuelta al llamador. Asegúrese de eliminar los rangos para garantizar un comportamiento predecible, ya que no usarlo funciona bien para mí en Windows, pero no en Mac.

El otro comportamiento que quiero destacar es hacer clic automáticamente en botones del sitio web en el que se ejecuta la extensión. Para hacer clic automáticamente en botones del navegador, debemos consultar la pestaña activa actual en la ventana actual y luego enviar un mensaje al script de contenido. Cuando el script de contenido recibe el mensaje, simplemente utiliza el método DOMDocumentQuerySelector con un selector para el botón que desea hacer clic automáticamente para obtener un elemento de botón. Luego, simplemente llama al método click en el elemento de botón. Nuestra respuesta se envía al llamador en función de si las operaciones fueron exitosas o no.

4. Calling External Services

Short description:

Llamamos a servicios externos utilizando la API Fetch. Solo el service worker puede llamar a la API Fetch sin errores de CORS. Pasamos mensajes desde el código de la extensión al script de contenido y luego transmitimos esos mensajes al script de fondo. Utilizamos una función auxiliar llamada selfSendRequest para enviar y manejar los mensajes. En el script de fondo, utilizamos la API Fetch para realizar solicitudes y enviar la respuesta o el error de vuelta al llamador.

El último comportamiento que quiero destacar es llamar a servicios externos. Llamamos a servicios externos utilizando la API Fetch. Un detalle importante es que solo el service worker puede llamar a la API Fetch sin errores de CORS. Por lo tanto, necesitamos pasar mensajes desde el código de la extensión al script de contenido, que es el único al que el código de la extensión puede enviar mensajes. Y luego, transmitir esos mensajes al script de fondo. He creado una función auxiliar llamada selfSendRequest que envía el mensaje al script de contenido y luego rechaza la respuesta si es un error o la resuelve a la respuesta. Luego, podemos llamar a este método de forma asíncrona con los detalles de nuestra solicitud. En el script de fondo, simplemente llamamos a una API Fetch estándar con una solicitud dada y luego enviamos la respuesta o un error de vuelta al llamador dependiendo de si la solicitud Fetch fue exitosa.

5. Running the Extension Locally

Short description:

Para ejecutar la extensión localmente, debes construirla, activar el modo de desarrollador y cargarla desde la carpeta de construcción en Administrar extensiones. Actualiza las páginas o ciérralas antes de cargar la extensión. Para Firefox, necesitas una versión diferente de la extensión debido al uso de scripts de fondo. Firefox utiliza el espacio de nombres del navegador para las APIs de JavaScript. Para agregar la extensión en Firefox, ve a Acerca de la depuración y carga una extensión temporal. Las extensiones de Chrome permanecen instaladas cuando se cargan sin empaquetar, mientras que las extensiones de Firefox son temporales. Para publicar en la Chrome Web Store, necesitas una cuenta de desarrollador y un archivo zip de la carpeta de construcción.

Lo siguiente de lo que quiero hablar es ejecutar la extensión localmente. Para ejecutar la extensión localmente, primero debes construir la extensión, lo cual creará la carpeta de construcción para ti. Luego puedes ir a Administrar extensiones, activar el modo de desarrollador y cargar sin empaquetar. Debes seleccionar la carpeta de construcción para cargar la extensión. Asegúrate de actualizar las páginas en las que la extensión debería estar funcionando después de la actualización. O preferiblemente no tenerlas abiertas al cargar la extensión.

Tengo un video para mostrarte cómo hacer esto. Así que ve a Administrar extensiones, lo que te llevará a esa URL. Luego puedes activar el modo de desarrollador, cargar sin empaquetar. Asegúrate de seleccionar la carpeta de construcción. Y ahí está tu extensión. Ahora puedes ir a Gmail en nuestro caso. Y puedes fijar la extensión en la parte superior derecha. Fija la extensión en la parte superior derecha. Y luego puedes hacer clic para abrir y cerrarla.

Si tienes una extensión en Chrome, puedes convertirla en una extensión de Firefox relativamente fácilmente. Tanto Chrome como Firefox están ejecutando actualmente la versión 3 del manifiesto. Sin embargo, Firefox no ha adoptado los Service Workers y todavía utiliza scripts de fondo. Esto significa que tu archivo Manifest.json será diferente, al menos en la línea de fondo. Y dado que ni Chrome ni Firefox permiten un nombre diferente para el archivo de manifiesto, debes tener una versión diferente de la extensión para cada navegador, incluso si todo lo demás es compatible.

En Firefox, las APIs de JavaScript se ejecutan bajo el espacio de nombres del navegador, a diferencia de Chrome. Pero para la compatibilidad cruzada, Firefox también acepta el uso de la palabra clave Chrome. Agregar la extensión en Firefox también es un poco diferente. Debes ir a Acerca de la depuración, hacer clic en este Firefox a la izquierda y luego presionar el botón Cargar extensión temporal. Tampoco puedes seleccionar toda la carpeta de construcción, pero cualquier archivo dentro de ella cargará la extensión. También vale la pena mencionar que mientras que las extensiones de Chrome permanecen instaladas cuando las cargas sin empaquetar, las extensiones de Firefox son temporales. Así que este es un ejemplo, esta es mi extensión actual que cargué temporalmente. Puedes verla allí, presionarla, se abre en una pestaña y puedes trabajar con ella.

Para publicar en la Chrome Web Store, necesitas una cuenta de desarrollador y un archivo zip de la carpeta de construcción.

6. Publishing, Demo, and Conclusion

Short description:

Antes de publicar la extensión de Chrome, pasa por un proceso de revisión. Lo mismo se aplica a los complementos de Firefox, que también requieren una revisión. La demostración muestra un sistema de gestión de correo electrónico con funciones como aplazamiento de correos electrónicos y toma de notas. Tex responde a correos electrónicos, agrega notas y genera nuevos correos electrónicos. La presentación concluye con recursos disponibles y una invitación a conectarse en LinkedIn o Twitter.

Antes de que esté disponible, la extensión de Chrome pasará por un proceso de revisión. Más detalles en ese enlace. Para publicar un complemento de Firefox, también necesitas una cuenta de desarrollador para Firefox en este caso. También necesitarás un archivo zip de tu carpeta de construcción o cualquiera de los otros tipos de paquetes aceptados. Cuando cargas la extensión, se somete a una validation automática. Después de pasar la validation, puedes enviar la extensión para su publicación. Los complementos de Firefox están disponibles inmediatamente después de la carga. Sin embargo, también pasarán por un proceso de revisión y podrían ser bloqueados más adelante.

Y esta es mi demostración. Para la demostración, Tex ha recibido un montón de correos electrónicos. Veamos este correo electrónico. Este es un correo electrónico al que Tex ha respondido. Solicitó un aplazamiento. Estas son las notas que agregó. La primera se genera automáticamente, con el texto del correo electrónico al que respondió. Puede agregar nuevas notas. Ahora, veamos un nuevo correo electrónico. Random Company quiere hablar con Tex. Podría responder a Adena, que trabaja en Random Company. Y me olvidé de la Y, así que Random Company. Y da una línea de tiempo, es el comienzo de agosto. Descubre qué hora del día es y luego puedes generar un correo electrónico. Verifica el contenido del correo electrónico y luego se puede enviar automáticamente. Aparece en las notas. Y aquí se pueden agregar más notas. Muy lentamente. Sí, y esta es mi presentación, esta es mi demostración. Si quieres leer más sobre la tecnología utilizada en esta charla, esta es una lista de recursos útiles. Las diapositivas estarán disponibles para ti. Y muchas gracias por escuchar mi charla. Puedes conectarte conmigo en LinkedIn o Twitter en adinotech21. Gracias.