Antes de escribir una extensión necesitas entender cómo encajan sus piezas. Muchos principiantes copian un manifest.json de un tutorial y se atascan en cuanto dos partes de la extensión necesitan comunicarse.
Esta nota presenta la arquitectura y la estructura que da sentido al resto.
MV3 es la vía para las extensiones actuales
La Chrome Web Store ya no acepta extensiones Manifest V2. Si empiezas hoy, construye con MV3.
El cambio principal es que las páginas persistentes en segundo plano desaparecen. Las sustituyen service workers que arrancan cuando hacen falta y pueden terminar al quedar inactivos. Los datos guardados solo en variables se pierden cuando termina el worker. Usa chrome.storage, como explico en cómo conservar el estado de una extensión.
Otros cambios de MV3:
chrome.scriptingsustituye achrome.tabs.executeScript.fetchsustituye aXMLHttpRequesten el contexto de segundo plano.- La política de seguridad de contenido es más estricta. Los scripts de la extensión deben incluirse en el paquete, en lugar de descargarse para ejecutarlos desde otro servidor.
- Declarative Net Request sustituye el uso habitual de
webRequestpara bloquear solicitudes, con excepciones de despliegue empresarial.
Los cuatro componentes principales
Una extensión puede usar estas cuatro piezas. No todas las necesitan, pero conviene conocerlas.
1. El popup
Es la pequeña interfaz que aparece al pulsar el icono de la extensión.
- Es una página HTML: puedes usar JavaScript, React, Vue o lo que convenga.
- Su estado en memoria es temporal. Al cerrarse se destruye y al abrirse se crea de nuevo.
- Puede llamar directamente a las APIs
chrome.*que tenga disponibles. - Puede comunicarse con otros componentes mediante mensajes.
Piensa en una pequeña aplicación que vive mientras está abierta. Si una tarea debe continuar al cerrarla, necesita otro contexto, como el service worker, y respetar su ciclo de vida.
Para construir uno, crea tu primera extensión con TypeScript desde cero. El tutorial usa Vite y CRXJS.
2. El service worker de segundo plano
Escucha eventos y coordina la extensión.
- Es un service worker, sin DOM,
windownidocument. - Puede terminar al quedar inactivo, normalmente tras treinta segundos, con las excepciones descritas en la documentación del ciclo de vida. Un nuevo evento puede volver a iniciarlo.
- Gestiona alarmas, mensajes, eventos de red y cambios de pestaña.
- Alberga la lógica de segundo plano que no debe depender de que el popup siga abierto.
Cuando termina, desaparecen sus variables globales. Conserva lo necesario en almacenamiento persistente; consulta cómo guardar el estado de una extensión.
3. El script de contenido
Se ejecuta dentro de las páginas web que visita el usuario.
- Puede leer y modificar el DOM e insertar elementos.
- Por defecto vive en un mundo aislado: comparte el DOM, pero no las variables JavaScript de la página. Puede leer un valor representado en un elemento, aunque no acceder directamente a una variable del script de la web.
- Puede usar
chrome.storagey los mensajes de runtime. Para APIs comochrome.tabs, delega en otro contexto de la extensión. Consulta las capacidades de los scripts de contenido. - Se declara en
content_scriptsdentro del manifiesto o se inyecta mediantechrome.scripting.executeScript.
Así interactúa una extensión con un sitio. Un bloqueador puede retirar elementos publicitarios; un gestor de contraseñas, rellenar campos.
4. La página de opciones
Es una interfaz completa de configuración.
- Se abre desde «Opciones» en el menú del icono o desde los detalles en
chrome://extensions. - Es una página HTML como el popup, pero dispone de más espacio.
- Sirve para ajustes que no caben en una ventana pequeña.
Una extensión sencilla puede prescindir de ella. Añádela cuando la cantidad de ajustes lo justifique.
Cómo se conectan las piezas
Los componentes se ejecutan en contextos separados. Para comunicar esos contextos de forma explícita se usan mensajes.
┌─────────────┐ messages ┌──────────────────┐
│ Popup │ ◄──────────────► │ Service Worker │
└─────────────┘ └──────────────────┘
▲
│ messages
▼
┌──────────────────┐
│ Content Script │
│ (inside webpage) │
└──────────────────┘
En este diseño, el service worker coordina el popup y los scripts de contenido. Es un patrón habitual, aunque el popup también puede enviar mensajes directamente a un script de contenido.
La guía de mensajes con TypeScript explica uniones discriminadas, tipos de respuesta y detalles de las llamadas asíncronas.
El manifiesto declara la estructura
manifest.json configura los componentes y las capacidades de la extensión:
manifest.json
├── action.default_popup → "popup.html"
├── background.service_worker → "background.js"
├── content_scripts → [{ matches, js }]
├── options_page → "options.html"
└── permissions → what APIs you can use
El manifiesto declara los puntos de entrada, los permisos y otras opciones. Algunas capacidades, como inyectar scripts dinámicamente, se configuran mediante las APIs correspondientes. Elegir bien los permisos ayuda a justificar el acceso que solicitas durante la revisión de la tienda.
Qué componentes necesitas
Depende de la tarea:
Solo popup: una calculadora, selector de color o consulta rápida puede funcionar sin worker ni scripts de contenido.
Popup y service worker: la interfaz inicia acciones que se gestionan en segundo plano, como alarmas o llamadas a APIs.
Popup, service worker y script de contenido: útil cuando hay interacción con páginas. Es el diseño que usa ResistGate: los scripts interactúan con las páginas, el worker coordina el estado y el popup muestra controles.
Solo script de contenido: modificaciones automáticas de páginas, como herramientas de lectura o cambios de apariencia.
Un mapa para recordar la arquitectura
Piensa en programas separados que comparten canales de comunicación:
- El popup es una interfaz pequeña y temporal que abre el usuario.
- El service worker responde a eventos y conserva fuera de la memoria lo que debe sobrevivir a sus reinicios.
- El script de contenido interactúa con la página.
- La página de opciones reúne los ajustes.
- Los mensajes conectan los contextos.
- El manifiesto declara cómo se organiza la extensión.
Por dónde continuar
Con ese mapa puedes empezar a construir:
- Crea tu primera extensión con TypeScript, desde una carpeta vacía hasta un popup funcional.
- Aprende a conectar componentes con la guía de mensajes con TypeScript.
- Conserva datos con los patrones de almacenamiento de extensiones.
Otras superficies disponibles
Chrome ofrece más opciones cuando el producto las necesita:
- Los paneles laterales mantienen una interfaz junto a una web sin depender de un popup que se cierra al perder el foco.
- Los documentos offscreen ofrecen un documento oculto para tareas que necesitan APIs del DOM no disponibles en el worker.
- La inyección dinámica de scripts de contenido permite usar
chrome.scripting.executeScriptcuando haga falta.
Una extensión pequeña puede empezar con un popup y añadir estas piezas después.
Esta nota forma parte de la serie Extensiones de Chrome: de cero a producto, donde explico lo que aprendí construyendo ResistGate y Amethyst, desde el primer popup hasta la publicación.
Un pequeño voto de confianza
¿Valió la pena leer esta nota?