Otimização do desempenho do site de alto tráfego: passo a passo para criar um plug-in BigRender adequado

BigRender

Quando um site fica cada vez maior e sua velocidade de carregamento fica cada vez mais lenta, os desenvolvedores precisam otimizá-lo. Quem quer visitar uma página da web que leva 10 segundos e 20 segundos para aparecer?

Uma solução de otimização comum e relativamente simples é o carregamento lento de imagens. Uma página enorme, às vezes não rolamos para ver o conteúdo abaixo, o que desperdiça a renderização da parte da tela que não é a primeira, e essas renderizações inúteis incluem não apenas imagens, mas também outros elementos DOM e até mesmo alguns js / css (Alguns js / css são solicitados com base em módulos, como alguns ajax.) Em teoria, cada DOM adicional aumentará o tempo de renderização. Existe uma maneira de fazer com que HTML, js, css possam ser carregados sob demanda? A resposta é sim, é sobre o BigRender que este artigo vai falar.

Existem muitos casos de BigRender no ambiente de produção da indústria, como Sina, Meituan, Tuniu Travel, navegação no site 360, página de detalhes do produto Taobao e assim por diante. Verifique o código-fonte (ctrl + u), ctrl + f pesquise a palavra-chave textarea, é fácil ver algum código HTML envolvido por tags textarea.

Por exemplo, Tuniu:

Otimização do desempenho do site de alto tráfego: passo a passo para criar um plug-in BigRender adequado

O código HTML envolvido pela tag textarea é apenas o valor de textarea e não é renderizado na árvore DOM. Isso mesmo, BigRender geralmente envolve o código HTML (js / css) com tags textarea como seu valor e espera o momento certo (geralmente quando a tag textarea aparece ou está prestes a aparecer no campo de visão do usuário) para retirar o código HTML na textarea Use innerHTML para inserir dinamicamente na árvore DOM, se necessário, retire o código js / css (regular) e execute-os dinamicamente. (É semelhante ao carregamento lento de imagens?)

Tio Yu apontou:

Após o download da página, ela precisa passar por Tokenization - Tree Construction - Rendering.Para fazer a primeira tela aparecer o mais rápido possível, o navegador deve reduzir a carga de trabalho de renderização da primeira tela. Você pode começar com dois aspectos:

  1. Reduza o número de nós DOM. Quanto menor o número de nós, menos tempo leva para operações como tokenização e renderização. (Para uma página de detalhes de produto Taobao típica, o teste descobriu que cada nó DOM adicional fará com que o tempo de renderização da primeira tela atrase cerca de 0,5 ms.)

  2. Reduza o tempo de execução do script. A execução do script e a atualização da IU compartilham um thread. Quanto menos tempo o script leva, mais rápida a atualização da IU.

Por que usar tags textarea para armazenar grandes blocos de conteúdo HTML? Você ainda pode ler este artigo do tio Yu. O kissy do Taobao possui um componente DataLazyload integrado. (Interlúdio: a página de detalhes de Meituan também usa a tag de script para a otimização do BigRender. Para obter detalhes, consulte a seção "Outros" abaixo)

Em seguida, implementarei um plug-in BigRender que se adapte a mim passo a passo.Eu espero poder atrasar o carregamento de elementos HTML, js e css.

T.datalazyload

Eu defini um objeto global T seguindo o caminho do jQuery, encapsulei o código de implementação do carregamento lento no objeto T.datalazyload, "embrulhei" o código que precisa do carregamento lento na tag textarea, configurei sua propriedade de visibilidade como oculta e atribuí A tag tem um nome de classe especial (para monitoramento de eventos), como "datalazyload". Por conveniência, estipulo que cada nó pai de uma textarea otimizada para bigrender tem apenas um filho (ou seja, o elemento textarea) .Isso é muito importante e deve ser observado, pois o código por trás tem processamento especial para isso. (Observe que a altura e a largura do nó pai devem ser definidas para serem consistentes com a altura e largura após a renderização dom)

Alguns códigos HTML / js / css podem ser agrupados em tags textarea, por exemplo:


<textarea class="datalazyload" style="visibility: hidden;">

  <script type="text/javascript">

    alert("I am lazyload zone!");

  </script>

  <style type="text/css">

    .main {margin: 0 auto; text-align: center; padding-top: 200px; width:1000px; height:1000px; border:5px black dashed;}

    .second {margin: 0 auto; width:1000px; height:200px; border: 5px purple dotted; padding-top: 100px; text-align: center;}

  </style>

  <div class="second">

    <h1>我是延迟加载的部分!</h1>

  </div>

</textarea>

iniciar

Defina um método init () para o objeto T.datalazyload. Quando a página é inicializada, ela escuta os eventos de rolagem, redimensionamento e touchmove no terminal móvel. Quando esses eventos são disparados, a função de retorno de chamada determina se a parte de carregamento atrasado apareceu na janela de visualização.


init: function(config) {

  var cls = config.cls;

  this.threshold = config.threshold ? config.threshold : 0;

  this.els = Array.prototype.slice.call(T.getElementsByClassName(cls));

  this.fn = this.pollTextareas.bind(this);

  this.fn();

  T.addEvent(window, "scroll", this.fn);

  T.addEvent(window, "resize", this.fn);

  T.addEvent(doc.body, "touchMove", this.fn);

}

config é um parâmetro de configuração e seu atributo cls representa o nome da classe da textarea que precisa ser carregada lentamente. Threshold é o threshold. A unidade é px, que indica quantos pixels a textarea está da janela de visualização antes do pré-carregamento.

Armazene o elemento que precisa ser carregado com atraso em uma matriz (this.els) e exclua o elemento da matriz assim que o carregamento subsequente for concluído (um elemento textarea). A função de retorno de chamada para monitoramento de eventos é o método pollTextarea ().

pollTextarea

pollTextareas: function() {

  // 需延迟加载的元素已经全部加载完

  if (!this.els.length) {

    T.removeEvent(window, "scroll", this.fn);

    T.removeEvent(window, "resize", this.fn);

    T.removeEvent(doc.body, "touchMove", this.fn);

    return;

  }

  // 判断是否需要加载

  for (var i = this.els.length; i--; ) {

    var ele = this.els[i];

    if (!this.inView(ele))

      continue;

    this.insert(ele);

    this.els.splice(i, 1);

  }

}

A função deste método é determinar se o elemento que precisa ser carregado lentamente já está na janela de visualização, se estiver, carregue-o (acionando o método de inserção) e exclua o elemento na matriz; se a matriz estiver vazia, indica que as partes que precisam ser carregadas lentamente são todas Após o carregamento, o ouvinte de evento é removido e todo o carregamento atrasado termina.

inserir

Em seguida, observe o método de inserção. O parâmetro do método inerte é o elemento textarea que precisa ser carregado lentamente. Obviamente, o código que precisamos analisar está todo em textarea.innerHTML. Usamos o método extractCode para retirar o código js / css e, em seguida, filtrar o js / css, de modo que o resto seja todo o código HTML e inseri-lo no DOM (este é exatamente o "nó pai de cada textarea" mencionado anteriormente Como há apenas um filho ", você pode usar diretamente a operação do nó pai innerHTML). Se houver um efeito de carregamento, geralmente adicione uma classe de carregamento ao nó pai e remova-a. Por fim, execute dinamicamente o script js e insira o estilo css.


insert: function(ele) {

  var parent = ele.parentNode

    , txt = this.decodeHTML(ele.innerHTML)

    , matchStyles = this.extractCode(txt, true)

    , matchScripts = this.extractCode(txt);

  parent.innerHTML = txt

    .replace(new RegExp("<script[^>]*>([\\S\\s]*?)</script\\s*>", "img"), "")

    .replace(new RegExp("<style[^>]*>([\\S\\s]*?)</style\\s*>", "img"), "");

  if (matchStyles.length)

    for (var i = matchStyles.length; i --;)

      this.evalStyles(matchStyles[i]);

  // 如果延迟部分需要做 loading 效果

  parent.className = parent.className.replace("loading", "");

  if (matchScripts.length)

    for (var i = 0, len = matchScripts.length; i < len; i++)

      this.evalScripts(matchScripts[i]);

},

extractCode

Tiramos as tags js e css por meio de regras regulares:


extractCode: function(str, isStyle) {

  var cata = isStyle ? "style" : "script"

    , scriptFragment = "<" + cata + "[^>]*>([\\S\\s]*?)</" + cata + "\\s*>"

    , matchAll = new RegExp(scriptFragment, "img")

    , matchOne = new RegExp(scriptFragment, "im")

    , matchResults = str.match(matchAll) || []

    , ret = [];

  for (var i = 0, len = matchResults.length; i < len; i++) {

    var temp = (matchResults[i].match(matchOne) || [ "", "" ])[1];

    temp && ret.push(temp);

  }

  return ret;

}

Extraiu com sucesso o conteúdo no script e nas tags de estilo e usou habilmente a subexpressão no regular.


evalScripts / evalStyles

Execução de script, renderização de estilo.


evalScripts: function(code) {

  var head = doc.getElementsByTagName("head")[0]

    , js = doc.createElement("script");

  js.text = code;

  head.insertBefore(js, head.firstChild);

  head.removeChild(js);

},

evalStyles: function(code) {

  var head = doc.getElementsByTagName("head")[0]

    , css = doc.createElement("style");

  css.type = "text/css";

  try {

    css.appendChild(doc.createTextNode(code));

  } catch (e) {

    css.styleSheet.cssText = code;

  }

  head.appendChild(css);

}

Vantagens e desvantagens e cenários aplicáveis

Fale brevemente sobre as vantagens e desvantagens da otimização do BigRender e os cenários aplicáveis.

As vantagens são óbvias. Como a renderização do DOM da primeira tela é reduzida, a velocidade de carregamento da primeira tela pode ser acelerada e o js / css pode ser carregado em blocos, o que é muito adequado para alguns sites com um alto grau de diferenciação de módulo (pessoalmente, acho que a diferenciação de módulo de grandes sites O grau está geralmente ficando cada vez mais alto).

A desvantagem é a necessidade de alterar a estrutura do DOM (a substituição e renderização dos nós do DOM), o que pode causar alguns rearranjos e redesenho. Alguns usuários que não habilitam a função js não verão o conteúdo de carregamento atrasado (você pode usar a tag noscript para dar um lembrete). A maior desvantagem pode ser o fato de não ser favorável ao SEO. Alguns sites que dependem do SEO podem precisar trabalhar muito no SEO, como o Meituan.

Com relação ao SEO, você pode consultar o site http://www.seoqx.com/lynx , que pode simular o rastreamento do site por spiders de mecanismos de pesquisa. Meituan para BigRender e soluções de SEO [caso Meituan.com] Melhore os problemas de SEO causados ​​pela tecnologia BigRender

bigrender acelera a renderização da primeira tela reduzindo os nós DOM, mas também tem perda de desempenho adicional. O código html na textarea antes da renderização é armazenado na textarea oculta no lado do servidor, portanto, será armazenado no lado do servidor. Escape do código HTML: colchetes angulares e assim por diante foram escapados, isso aumentará a pressão no servidor; além disso, essa transformação é apenas a renderização de front-end, o servidor ainda calcula todos os dados e exibe todos os dados de uma vez, isso não foi melhorado.

De um modo geral, o back-end é dividido em strings html, depois inserido na tag textarea e cuspido no front end.

demo

Se você quiser fazer uma demonstração completa do BigRender, pode ser mais complicado e envolver o backend.

Quando eu estava aprendendo lazyload antes, fiz uma demonstração de imagem lazyloading, consulte http://hanzichi.github.io/2015/picture-lazyload/. Como o BigRender é uma versão aprimorada do lazyload, simplesmente fiz uma versão do BigRender do carregamento lento de imagem http://hanzichi.github.io/2016/bigrender/, o código específico pode ser verificado https://github.com/hanzichi /hanzichi.github.io/blob/master/2016/bigrender/js/bigrender.js. Peça estrela, peça garfo ~

de outros

Além de usar textarea para otimização do BigRender na página inicial, a Meituan também usou tags de script para otimização. Por exemplo, esta página de detalhes do produto

Otimização do desempenho do site de alto tráfego: passo a passo para criar um plug-in BigRender adequado

Defina um tipo diferente de "text / javascript" para a tag de script, você pode baixar este js, mas não execute.Esta abordagem parece familiar e foi vista em labjs.

Para obter mais informações, consulte a terceira continuação da otimização front-end: use script para armazenar o código html para reduzir o número de nós DOM


consulte Mais informação

  • Otimização do BigRender da página de detalhes do Taobao e a melhor maneira de armazenar grandes blocos de conteúdo HTML

  • Otimização de front-end: renderização atrasada de textarea do BigRender e a prática de LABjs

  • lazyload componentes de carregamento lento

  • Aplicativo lento de carregamento lento de dados KISSY

  • código-fonte de kissy datalazyload.js

  • API de dataLazyload de kissy

  • demos do DataLazyload com beijo

Acho que você gosta

Origin blog.51cto.com/15080022/2588312
Recomendado
Clasificación