ReportingObserver: Conoce el estado de tu código

A modo de 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 encuentra con 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 proveedor de backend o de estadísticas para un análisis más detallado.

¿Por qué es útil? Hasta ahora, las advertencias de baja y de intervención solo estaban disponibles en DevTools 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, existen otros tipos de advertencias que estas APIs existentes no detectan. Cuando tu sitio usa una API obsoleta o se encuentra con una intervención del navegador, DevTools es el primero en informarte 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 se activa para las advertencias que genera directamente el usuario-agente. Se activa por errores de tiempo de ejecución (excepciones de JS y errores de sintaxis) causados por la ejecución de tu código.

ReportingObserver aumenta la carga. Proporciona una forma programática de recibir notificaciones sobre advertencias emitidas por el navegador, como bajas y intervenciones. Puedes usarlo como herramienta de informes y olvidarte de preocuparte por si los usuarios tienen problemas inesperados en tu sitio activo.

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 filtrar previamente 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 muy útil cuando deseas ver los informes que se generaron antes de crear el observador:

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

Es excelente 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: Recibir una notificación cuando se quitarán 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 brinda una forma adicional de descubrir y supervisar posibles problemas en tu app web. Incluso es una herramienta útil para comprender el estado de tu 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 entusiasman las herramientas que integran ReportingObserver en sus flujos de trabajo. Lighthouse es un ejemplo de una herramienta que ya marca las baja de los navegadores cuando ejecutas su 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 DevTools para extraer mensajes de la consola y notificar 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: