ReportingObserver: Conoce el estado de tu código

Resumen

¡Hay un nuevo observador en la ciudad! ReportingObserver es una nueva API 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 proveedor de backend o de estadísticas a fin de realizar un análisis más detallado.

¿Por qué es útil? Hasta ahora, las advertencias de baja y intervención solo estaban disponibles en las Herramientas para desarrolladores como mensajes de la consola. Las intervenciones, en particular, solo se activan mediante varias restricciones reales, como las condiciones del dispositivo y la red. Por lo tanto, es posible que nunca veas estos mensajes cuando desarrollas o pruebas un sitio de forma local. ReportingObserver proporciona la solución a este problema. Cuando los usuarios experimentan posibles problemas en su naturaleza, se nos puede notificar al respecto.

Introducción

Hace un tiempo, escribí una entrada de blog ("Observa tu app web") porque me resultaba fascinante cuántas APIs hay para supervisar los "cosas" que se producen 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 con una intervención del navegador, Herramientas para desarrolladores primero te lo indican:

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

Uno sería naturalmente pensar que window.onerror captura estas advertencias. No. Esto se debe a que window.onerror no se activa para las advertencias que genera directamente el usuario-agente. Se activa para detectar errores de tiempo de ejecución (errores de sintaxis y de excepciones de JS) causados por la ejecución del código.

ReportingObserver se pone a tono con la holgura. Proporciona una forma programática de recibir notificaciones sobre advertencias emitidas por el navegador, como intervenciones y bajas. Puedes usarla como herramienta de informes y perder menos sueño preguntándote si los usuarios tienen problemas inesperados en tu sitio en vivo.

La API

La API no difiere 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

Se puede aplicar un filtro previo a los informes 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 quieres 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 que ocurrió 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 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 este). Envía informes a un backend, conoce los problemas reales que tienen 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 práctica para capturar todos los tipos 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 bajas de los navegadores cuando ejecutas su auditoría de "Evita las APIs obsoletas":

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

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

Recursos adicionales: