Cómo intervenir en document.write()

¿Has visto recientemente una advertencia como la siguiente en tu Developer Console en Chrome y te preguntaste qué era?

(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.

La componibilidad es uno de los grandes poderes de la Web, ya que nos permite integrarse con servicios creados por terceros para crear excelentes productos nuevos. Uno Una de las desventajas de la componibilidad es que implica una responsabilidad compartida sobre la experiencia del usuario. Si la integración no es óptima, la experiencia del usuario se verán afectados negativamente.

Una causa conocida del rendimiento deficiente es el uso de document.write() dentro de las páginas. específicamente, aquellos usos que insertan secuencias de comandos. Por más inocua que se ve, pueden causar problemas reales a los usuarios.

document.write('<script src="https://example.com/ad-inject.js"></script>');

Antes de que el navegador pueda representar una página, debe compilar el árbol del DOM analizando el lenguaje de marcado HTML. Cuando el analizador encuentra una secuencia de comandos, debe detenerla y ejecutarla para poder continuar. que analizan el HTML. Si la secuencia de comandos inserta otra de forma dinámica, el analizador se verá obligado a esperar. incluso más tiempo para que el recurso lo descargue, lo que puede incurrir en uno o más recorridos de red y retrasar el tiempo en la primera renderización de la página

Para usuarios con conexiones lentas, como 2G, secuencias de comandos externas dinámicamente La inserción a través de document.write() puede retrasar la visualización del contenido de la página principal en decenas de segundos, o hacer que las páginas no se carguen o tarden tanto que la el usuario se rinde. A partir de la instrumentación en Chrome, aprendimos que las páginas con secuencias de comandos de terceros insertadas a través de document.write() se en general el doble de lento que otras páginas en 2G.

Recopilamos datos de una prueba de campo de 28 días en el 1% de Chrome estables, restringida a aquellos con conexiones 2G. Vimos que el 7.6% de todas las cargas de la página en 2G incluía al menos una secuencia de comandos entre sitios que bloquea el analizador que estaba insertada a través de document.write() en el documento de nivel superior. Como resultado del bloqueo durante la carga de estas secuencias de comandos, vimos las siguientes mejoras en esas cargas:

  • Un 10% más de cargas de página que llegan primer procesamiento de imagen con contenido (una confirmación visual para el usuario de que la página se está cargando eficazmente) Un 25% más de cargas de página para alcanzar el estado de análisis completo y un 10% menos de recargas lo que sugiere una disminución en la frustración de los usuarios.
  • Un 21% de disminución del tiempo promedio (más de un segundo más rápido) hasta que la primer procesamiento de imagen con contenido
  • Una reducción del 38% en el tiempo promedio que lleva analizar una página, lo que representa un de casi seis segundos, lo que reduce drásticamente el tiempo que se necesita para mostrar lo que le importa al usuario.

Con estos datos en mente, Chrome, a partir de la versión 55, interviene en nombre de todos usuarios cuando detectamos este patrón conocido como incorrecto cambiando la forma en que document.write() se maneja en Chrome (Consulta Estado de Chrome). Específicamente, Chrome no ejecutará los elementos <script> insertados a través de document.write() cuando se cumplen todas las siguientes condiciones:

  1. El usuario tiene una conexión lenta, en especial cuando está en 2G. (en en el futuro, el cambio podría extenderse a otros usuarios con conexiones lentas como una conexión 3G o Wi-Fi lenta).
  2. El document.write() se encuentra en un documento de nivel superior. La intervención no se aplican a las secuencias de comandos document.writing en iframes, ya que no bloquean la procesamiento de la página principal.
  3. La secuencia de comandos de document.write() bloquea el analizador. Scripts con el 'async' o "defer" seguirán ejecutándose los atributos.
  4. La secuencia de comandos no está alojada en el mismo sitio. En otras palabras, Chrome no intervenir para secuencias de comandos con un eTLD+1 coincidente (p.ej., una secuencia de comandos alojada en js.example.org insertado en www.example.org).
  5. La secuencia de comandos aún no se encuentra en la caché HTTP del navegador. Secuencias de comandos en la caché no incurrirá en un retraso de red y seguirá ejecutándose.
  6. La solicitud de la página no es una recarga. Chrome no intervendrá si el usuario activó una recarga y ejecutará la página normalmente.

Los fragmentos de terceros a veces usan document.write() para cargar secuencias de comandos. Afortunadamente, la mayoría de los socios externos proporcionan alternativas de carga asíncrona, que permite que las secuencias de comandos de terceros se carguen sin bloquear la visualización del resto del el contenido de la página.

¿Cómo puedo solucionarlo?

Esta respuesta simple es no insertar secuencias de comandos con document.write(). Mié Mantener un conjunto de servicios conocidos para la compatibilidad con cargador asíncrono que le recomendamos que siga revisando.

Si tu proveedor no está en la lista y admite la carga asíncrona de secuencias de comandos avísanos para que actualicemos la página a fin de ayudar a todos los usuarios.

Si tu proveedor no admite la capacidad de cargar secuencias de comandos de forma asíncrona en tu página, te animamos a que te pongas en contacto con ellos y avísennos cómo se verán afectados.

Si tu proveedor te proporciona un fragmento que incluye el document.write(), este Puedes agregar un atributo async al elemento de la secuencia de comandos. para que agregues los elementos de la secuencia de comandos con las APIs del DOM, como document.appendChild() o parentNode.insertBefore().

Cómo detectar cuándo tu sitio se ve afectado

Hay muchos criterios que determinan si se aplica la restricción ¿Cómo saber si la situación te afecta?

Cómo detectar cuando un usuario está en 2G

Para entender el impacto potencial de este cambio, primero tiene que entender cuántos de tus usuarios estarán en 2G. Puedes detectar el tipo de red actual del usuario y velocidad mediante la API de Network Information, que está disponible en Chrome y, luego, envía avisos a tus métricas analíticas o de usuarios reales (RUM).

if(navigator.connection &&
    navigator.connection.type === 'cellular' &&
    navigator.connection.downlinkMax <= 0.115) {
    // Notify your service to indicate that you might be affected by this restriction.
}

Detecta advertencias en Herramientas para desarrolladores de Chrome

Desde Chrome 53, Herramientas para desarrolladores emite advertencias sobre document.write() problemático declaraciones. Específicamente, si una solicitud document.write() cumple con los criterios 2 a 5 (Chrome ignora los criterios de conexión al enviar esta advertencia); la advertencia se verán algo así:

Advertencia de escritura de documento.

Ver advertencias en Herramientas para desarrolladores de Chrome es genial, pero ¿cómo puedes detectarlas en o escalar? Puedes verificar los encabezados HTTP que se envían a tu servidor cuando la intervención de software.

Verifica los encabezados HTTP en el recurso de secuencia de comandos

Si se bloquea una secuencia de comandos insertada a través de document.write, Chrome enviará siguiente encabezado al recurso solicitado:

Intervention: <https://shorturl/relevant/spec>;

Cuando se encuentra una secuencia de comandos insertada a través de document.write y esta podría bloquearse en en diferentes circunstancias, Chrome podría enviar lo siguiente:

Intervention: <https://shorturl/relevant/spec>; level="warning"

El encabezado de intervención se enviará como parte de la solicitud GET de la secuencia de comandos (de forma asíncrona en caso de una intervención real).

¿Qué nos depara el futuro?

El plan inicial es ejecutar esta intervención cuando detectemos los criterios que se está cumpliendo. Comenzamos mostrando solo una advertencia en Play Console en Chrome 53. (La versión beta se realizó en julio de 2016. Esperamos que el canal estable esté disponible para todos los usuarios de septiembre de 2016).

Interveniremos para bloquear las secuencias de comandos insertadas para los usuarios de 2G provisoriamente a partir de Chrome 54, que se estima que es una versión estable para todos los usuarios de mediados de octubre de 2016. Consulta la Entrada de estado de Chrome para conocer más novedades.

Con el tiempo, intentaremos intervenir cuando los usuarios tengan una conexión lenta (es decir, conexión 3G o Wi-Fi lenta). Sigue esta entrada sobre el estado de Chrome.

¿Quieres obtener más información?

Para obtener más información, consulta estos recursos adicionales: