Você viu recentemente um aviso como o seguinte no console do desenvolvedor do Chrome e se perguntou o que 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.
A composição é um dos grandes poderes da Web, permitindo-nos faça a integração com serviços de terceiros para desenvolver novos produtos incríveis. Um das desvantagens da composição é que ela implica uma responsabilidade compartilhada sobre a experiência do usuário. Se a integração não for ideal, a experiência do usuário serão prejudicadas.
Uma causa conhecida de desempenho insatisfatório é o uso de document.write()
dentro das páginas,
especificamente os usos que injetam scripts. Por mais inofensiva que pareça, ela
pode causar problemas reais para os usuários.
document.write('<script src="https://example.com/ad-inject.js"></script>');
Antes que o navegador possa renderizar uma página, ele precisa criar a árvore do DOM analisando a marcação HTML. Sempre que o analisador encontra um script, precisa interrompê-lo e executá-lo antes de continuar ao analisar o HTML. Se o script injetar dinamicamente outro script, o analisador será forçado a aguardar o download do recurso por mais tempo, o que pode resultar em uma ou mais idas e voltas na rede atrasar a primeira renderização da página
Para usuários com conexões lentas, como 2G, scripts externos dinamicamente
injetada pelo document.write()
pode atrasar a exibição do conteúdo da página principal para
vários segundos, ou fazer com que as páginas não carreguem ou demorem tanto que o
o usuário desiste. Com base na instrumentação do Chrome, aprendemos que
as páginas com scripts de terceiros inseridos por document.write()
estão
o carregamento geralmente é duas vezes mais lento do que outras páginas em 2G.
Coletamos dados de um teste de 28 dias em 1% do Chrome
usuários estáveis, restritos a usuários em conexões 2G. Notamos que 7,6% de todos os carregamentos de página
em 2G incluía pelo menos um script de bloqueio de analisador entre sites
inserido pelo document.write()
no documento de nível superior. Como resultado do bloqueio
o carregamento desses scripts, notamos as seguintes melhorias nesses carregamentos:
- 10% mais carregamentos de página alcançando First Contentful Paint (uma confirmação visual para o usuário de que a página está carregando efetivamente), 25% mais carregamentos de página alcançando o estado totalmente analisado e 10% menos atualizações sugerindo uma diminuição da frustração do usuário.
- 21% de redução do tempo médio (mais de um segundo mais rápido) até que o First Contentful Paint
- 38% de redução ao tempo médio necessário para analisar uma página, representando uma de quase seis segundos, reduzindo drasticamente o tempo que ele leva para mostrar o que é importante para o usuário.
Com esses dados em mente, o Chrome, a partir da versão 55,
intervir em nome de todos
quando detectamos esse padrão inadequado, mudando a forma como document.write()
é
manualmente no Chrome (consulte Status do Chrome).
Especificamente, o Chrome não executará os elementos <script>
injetados via
document.write()
quando todas as condições a seguir são atendidas:
- O usuário está com uma conexão lenta, especificamente quando está em 2G. (Em no futuro, a mudança pode ser estendida para outros usuários em conexões lentas, como conexão 3G lenta ou Wi-Fi lento).
- O
document.write()
está em um documento de nível superior. A intervenção não são aplicadas a scripts document.scritos em iframes, porque não bloqueiam renderização da página principal. - O script no
document.write()
bloqueia o analisador. Scripts com o campo "async
" ou "defer
" atributos ainda serão executados. - O script não está hospedado no mesmo site. Em outras palavras, o Chrome não intervir em scripts com um eTLD+1 correspondente (por exemplo, um script hospedado em js.example.org inserida em www.example.org).
- O script ainda não está no cache de HTTP do navegador. Scripts no cache não vai causar atrasos na rede e ainda será executado.
- A solicitação da página não é uma atualização. O Chrome não intervém se a o usuário acionou uma atualização e executará a página normalmente.
Às vezes, os snippets de terceiros usam document.write()
para carregar scripts.
Felizmente, a maioria dos terceiros fornece
alternativas de carregamento assíncrono, que
que scripts de terceiros sejam carregados sem bloquear a exibição do restante
o conteúdo da página.
Como resolvo esse problema?
A resposta simples é não injetar scripts usando document.write()
. Qa
manter um conjunto de serviços conhecidos para suporte a carregador assíncrono.
que recomendamos que você continue verificando.
Se o provedor não estiver na lista e oferecer suporte ao carregamento de script assíncrono Informe-nos para que possamos atualizar a página e ajudar todos os usuários.
Se o provedor não oferecer suporte à capacidade de carregar scripts de forma assíncrona na sua página, então recomendamos que você entre em contato com eles e avise nossa equipe e eles como elas serão afetadas.
Se o provedor fornecer um snippet que inclua o document.write()
, ele
talvez seja possível adicionar um atributo async
ao elemento de script ou
para você adicionar os elementos de script com a API DOM, como document.appendChild()
.
ou parentNode.insertBefore()
.
Como detectar quando seu site é afetado
Há um grande número de critérios que determinam se a restrição é aplicada, então, como saber se você foi afetado?
Como detectar quando um usuário está usando 2G
Para entender o possível impacto dessa mudança, primeiro você precisa entender quantos usuários usarão 2G. Você pode detectar o tipo de rede atual do usuário e velocidade usando a API Network Information, que está disponível no Chrome e envie um aviso para suas métricas analíticas ou de usuários reais (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.
}
Detectar avisos no Chrome DevTools
Desde o Chrome 53, o DevTools emite avisos para document.write()
problemáticos
declarações. Especificamente, se uma solicitação document.write()
atender aos critérios 2 a 5
O Chrome ignora os critérios de conexão ao enviar esse aviso.
é semelhante a:
Ver avisos no Chrome DevTools é ótimo, mas como detectar isso em escala? Você pode verificar cabeçalhos HTTP que são enviados ao seu servidor quando o antes da intervenção.
Verifique seus cabeçalhos HTTP no recurso de script
Quando um script inserido por document.write
for bloqueado, o Chrome enviará o
seguinte cabeçalho ao recurso solicitado:
Intervention: <https://shorturl/relevant/spec>;
Quando um script inserido via document.write
é encontrado e pode ser bloqueado
diferentes circunstâncias, o Chrome poderá enviar:
Intervention: <https://shorturl/relevant/spec>; level="warning"
O cabeçalho da intervenção será enviado como parte da solicitação GET para o script (de forma assíncrona, no caso de uma intervenção real).
O que o futuro reserva?
O plano inicial é executar essa intervenção quando detectarmos os critérios sendo atendidos. Começamos mostrando apenas um aviso no Play Console no Chrome 53. A versão Beta foi em julho de 2016. A expectativa é que o Stable esteja disponível para todos os usuários em Setembro de 2016.)
Interviremos para bloquear provisoriamente scripts injetados para usuários de 2G a partir de Chrome 54, que deve ter uma versão estável para todos os usuários no meados de outubro de 2016. Consulte o Entrada de status do Chrome para mais atualizações.
Com o tempo, tentamos intervir quando algum usuário tem uma conexão lenta (por exemplo, conexão 3G ou Wi-Fi lento). Siga esta entrada de status do Chrome.
Quer saber mais?
Para saber mais, consulte estes recursos extras:
- Especificação da intervenção document.write() e dos ciclos de feedback dela
- Status do Chrome (intervenção para usuários em 2G)
- Status do Chrome (intervenção para usuários em conexões efetivamente lentas)
- Documento de design
- Justificativa adicional para este esforço
- Intent blink-dev para implementar a linha de execução