ReportingObserver: Conoce el estado de tu código

Resumen

Hay un nuevo observador en la ciudad. ReportingObserver es una API nueva que te permite saber cuándo tu sitio usa una API obsoleta o se ejecuta en una intervención del navegador:

const observer = new ReportingObserver(
  (reports, observer) => {
    for (const report of reports) {
      console.log(report.type, report.url, report.body);
    }
  },
  {buffered: true}
);

observer.observe();

La devolución de llamada se puede usar para enviar informes a un backend o proveedor de estadísticas para analizarlos en detalle.

¿Por qué es útil? Hasta ahora, las advertencias de intervención y baja solo estaban disponibles en Herramientas para desarrolladores como mensajes de la consola. Las intervenciones, en particular, solo se activan debido a varias restricciones del mundo real, como condiciones del dispositivo y la red. Por lo tanto, es posible que nunca veas estos mensajes cuando desarrolles o pruebes un sitio de forma local. ReportingObserver proporciona la solución a este problema. Cuando los usuarios experimentan problemas en el entorno, podemos recibir notificaciones.

Introducción

Hace un tiempo, escribí una entrada de blog ("Observing your web app") porque me pareció fascinante la cantidad de APIs que hay para supervisar lo que ocurre en una app web. Por ejemplo, hay APIs que pueden observar información sobre el DOM: ResizeObserver, IntersectionObserver, MutationObserver. Hay APIs para capturar mediciones de rendimiento: PerformanceObserver. Otras APIs, como window.onerror y window.onunhandledrejection, incluso nos informan cuando algo sale mal.

Sin embargo, hay otros tipos de advertencias que estas APIs existentes no capturan. Cuando tu sitio usa una API obsoleta o se ejecuta en una intervención del navegador, primero las Herramientas para desarrolladores te informan al respecto:

Advertencias de la consola de Herramientas para desarrolladores sobre intervenciones y bajas.
Advertencias iniciadas por el navegador en la consola de Herramientas para desarrolladores.

Naturalmente, uno pensaría que window.onerror captura estas advertencias. ¡No lo hace! Esto se debe a que window.onerror no activa advertencias generadas directamente por el usuario-agente. Se activa por errores de tiempo de ejecución (excepciones de JS y errores de sintaxis) causados por la ejecución del código.

ReportingObserver aumenta la carga. Proporciona una forma programática de recibir notificaciones sobre las advertencias emitidas por el navegador, como las intervenciones y las bajas. Puedes usarlo como una herramienta de informes y perder menos tiempo de inactividad para preguntarte si los usuarios experimentan problemas inesperados en tu sitio publicado.

La API

La API no es diferente de las otras APIs de "observador", como IntersectionObserver y ResizeObserver. Le das una devolución de llamada y te da información. La información que recibe la devolución de llamada es una lista de los problemas que causó la página:

const observer = new ReportingObserver((reports, observer) => {
  for (const report of reports) {
    // → report.type === 'deprecation'
    // → report.url === 'https://reporting-observer-api-demo.glitch.me'
    // → report.body.id === 'XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload'
    // → report.body.message === 'Synchronous XMLHttpRequest is deprecated...'
    // → report.body.lineNumber === 11
    // → report.body.columnNumber === 22
    // → report.body.sourceFile === 'https://reporting-observer-api-demo.glitch.me'
    // → report.body.anticipatedRemoval === <JS_DATE_STR> or null
  }
});

observer.observe();

Informes filtrados

Los informes se pueden aplicar con un filtro previo para observar solo ciertos tipos de informes:

const observer = new ReportingObserver((reports, observer) => {
  ...
}, {types: ['deprecation']});

Informes almacenados en búfer

La opción buffered: true es realmente útil cuando deseas ver los informes que se generaron antes de que se creara el observador:

const observer = new ReportingObserver((reports, observer) => {
  ...
}, {types: ['intervention'], buffered: true});

Es ideal para situaciones como la carga diferida de una biblioteca que usa un ReportingObserver. El observador se agrega tarde, pero no te pierdes nada de lo que sucedió antes en la carga de la página.

Dejar de observar

Así es. Tiene un método disconnect:

observer.disconnect(); // Stop the observer from collecting reports.

Ejemplos

Ejemplo: informa las intervenciones del navegador a un proveedor de estadísticas:

const observer = new ReportingObserver(
  (reports, observer) => {
    for (const report of reports) {
      sendReportToAnalytics(JSON.stringify(report.body));
    }
  },
  {types: ['intervention'], buffered: true}
);

observer.observe();

Ejemplo: Recibe una notificación cuando se quiten las APIs:

const observer = new ReportingObserver((reports, observer) => {
  for (const report of reports) {
    if (report.type === 'deprecation') {
      sendToBackend(`Using a deprecated API in ${report.body.sourceFile} which will be
                     removed on ${report.body.anticipatedRemoval}. Info: ${report.body.message}`);
    }
  }
});

observer.observe();

Conclusión

ReportingObserver te proporciona una forma adicional de descubrir y supervisar posibles problemas en tu app web. Incluso es una herramienta útil para comprender el estado de la base de código (o la falta de ella). Envía informes a un backend, conoce los problemas reales que enfrentan los usuarios en tu sitio, actualiza el código y obtén ganancias.

Trabajo futuro

En el futuro, espero que ReportingObserver se convierta en la API de facto para detectar todo tipo de problemas en JS. Imagina una API para detectar todo lo que sale mal en tu app:

También me entusiasma la idea de contar con herramientas que integren ReportingObserver en sus flujos de trabajo. Lighthouse es un ejemplo de una herramienta que ya marca las bajas del navegador cuando ejecutas la auditoría "Evita las APIs obsoletas":

La auditoría de Lighthouse para usar APIs obsoletas podría usar ReportingObserver.
La auditoría de Lighthouse para usar APIs obsoletas podría usar ReportingObserver.

Actualmente, Lighthouse usa el protocolo de Herramientas para desarrolladores para extraer los mensajes de la consola y, luego, informar estos problemas a los desarrolladores. En cambio, podría ser interesante cambiar a ReportingObserver para obtener informes de baja bien estructurados y metadatos adicionales, como la fecha de anticipatedRemoval.

Recursos adicionales: