Optimización del rendimiento del sitio web de alto tráfico: paso a paso para crear un complemento de BigRender adecuado

BigRender

Cuando un sitio web se hace cada vez más grande y su velocidad de carga se vuelve cada vez más lenta, los desarrolladores tienen que optimizarlo ¿Quién quiere visitar una página web que tarda 10 segundos y 20 segundos en aparecer?

Una solución de optimización común y relativamente simple es la carga diferida de imágenes. Una página enorme, a veces no nos desplazamos para ver el contenido a continuación, lo que desperdicia la representación de la parte que no es la primera pantalla, y estas representaciones inútiles incluyen no solo imágenes, sino también otros elementos DOM, e incluso algunos js / css (Algunos js / css se solicitan en base a módulos, como algunos ajax.) En teoría, cada DOM adicional aumentará el tiempo de renderizado. ¿Hay alguna manera de hacer que HTML, js, css se puedan cargar a pedido? La respuesta es sí, este es BigRender del que hablará este artículo.

Hay muchos casos de BigRender en el entorno de producción de la industria, como Sina, Meituan, Tuniu Travel, navegación en el sitio web 360, página de detalles del producto Taobao, etc. Verifique su código fuente (ctrl + u), ctrl + f busque palabras clave de área de texto, es fácil ver algún código HTML envuelto por etiquetas de área de texto.

Por ejemplo, Tuniu:

Optimización del rendimiento del sitio web de alto tráfico: paso a paso para crear un complemento de BigRender adecuado

El código HTML envuelto por la etiqueta textarea es solo el valor del textarea y no se representa en el árbol DOM. Así es, BigRender generalmente envuelve el código HTML (js / css) con etiquetas textarea, como su valor de valor, y espera el momento adecuado (generalmente cuando aparece la etiqueta textarea o está a punto de aparecer en el campo de visión del usuario) para eliminar el código HTML en el área de texto. Use innerHTML para insertar dinámicamente en el árbol DOM, si es necesario, saque el código js / css (normal) y ejecútelo dinámicamente. (¿Es similar a la carga diferida de imágenes?)

El tío Yu señaló:

Después de descargar la página, debe pasar por Tokenización - Construcción de árbol - Representación. Para que la primera pantalla aparezca lo antes posible, el navegador tiene que reducir la carga de trabajo de renderizar la primera pantalla. Puedes partir de dos aspectos:

  1. Reducir la cantidad de nodos DOM. Cuanto menor sea el número de nodos, menos tiempo se necesita para operaciones como la tokenización y el renderizado. (Para una página de detalles de producto típica de Taobao, la prueba encontró que cada nodo DOM adicional provocará que el tiempo de visualización de la primera pantalla se demore alrededor de 0,5 ms).

  2. Reducir el tiempo de ejecución del script. La ejecución del script y la actualización de la interfaz de usuario comparten un hilo. Cuanto menos tiempo lleve el script, más rápida será la actualización de la interfaz de usuario.

¿Por qué utilizar etiquetas de área de texto para almacenar grandes cantidades de contenido HTML? Todavía puedes leer este artículo del tío Yu. Kissy de Taobao tiene un componente DataLazyload incorporado. (Interludio: la página de detalles de Meituan también usa la etiqueta de secuencia de comandos para la optimización de BigRender. Para obtener más detalles, consulte la sección "Otros" a continuación)

A continuación, implementaré un complemento de BigRender que me convenga paso a paso. Espero poder retrasar la carga de elementos HTML, js y css.

T.datalazyload

Definí un objeto global T, imitando la forma en que jQuery escribe, y encapsulé el código de implementación de carga diferida en el objeto T.datalazyload, y "envolví" el código que necesita carga diferida en la etiqueta textarea, configuré su atributo de visibilidad en oculto y asigné La etiqueta tiene un nombre de clase especial (para la supervisión de eventos), como "datalazyload". Por conveniencia, estipulo que cada nodo padre de un área de texto optimizada por bigrender tiene solo un hijo (es decir, el elemento textarea) .Esto es muy importante y debe tenerse en cuenta, porque el código detrás tiene un procesamiento especial para esto. (Tenga en cuenta que la altura y el ancho del nodo principal deben configurarse para que sean coherentes con la altura y el ancho después de la representación dom)

Algunos códigos HTML / js / css se pueden incluir en etiquetas de área de texto, por ejemplo:


<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>

en eso

Defina un método init () para el objeto T.datalazyload. Cuando se inicializa la página, escucha los eventos de desplazamiento, cambio de tamaño y movimiento táctil en el terminal móvil. Cuando se activan estos eventos, la función de devolución de llamada determina si la parte de carga retrasada ha aparecido en la ventana gráfica.


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 es un parámetro de configuración y su atributo cls representa el nombre de clase del área de texto que debe cargarse de forma diferida. Threshold es el umbral. La unidad es px, que indica cuántos píxeles tiene el área de texto de la ventana gráfica antes de la precarga.

Almacene el elemento que necesita cargarse con retraso en una matriz (this.els) y elimine el elemento de la matriz una vez que se complete la carga posterior (un elemento textarea). La función de devolución de llamada para el monitoreo de eventos es el 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);

  }

}

La función de este método es determinar si el elemento que debe cargarse de forma diferida ya está en la ventana gráfica; si lo está, cárguelo (activando el método de inserción) y elimine el elemento de la matriz; si la matriz está vacía, indica que las partes que deben cargarse de forma diferida son todas Después de la carga, el detector de eventos se elimina y se termina toda la carga retrasada.

insertar

A continuación, observe el método de inserción. El parámetro del método inerte es el elemento textarea que necesita cargarse de forma perezosa. Obviamente, el código que necesitamos analizar está todo en textarea.innerHTML. Usamos el método extractCode para sacar el código js / css, y luego filtrar el js / css, para que el resto sea todo código HTML, e insertarlo en el DOM (este es exactamente el "nodo principal de cada área de texto" mencionado anteriormente Debido a que solo hay un hijo ", puede usar directamente la operación innerHTML del nodo principal). Si hay un efecto de carga, generalmente agregue una clase de carga al nodo principal y elimínela. Finalmente, ejecute dinámicamente el script js e inserte el 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

Eliminamos las etiquetas js y css mediante reglas 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;

}

Extrajo con éxito el contenido del guión y las etiquetas de estilo, y usó inteligentemente la subexpresión en el formato regular.


evalScripts / evalStyles

Ejecución de script, renderizado 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);

}

Ventajas y desventajas y escenarios aplicables

Hable brevemente sobre las ventajas y desventajas de la optimización de BigRender y los escenarios aplicables.

Las ventajas son obvias. Debido a que se reduce el renderizado del DOM de la primera pantalla, se puede acelerar la velocidad de carga de la primera pantalla y se puede cargar js / css en bloques, lo cual es muy adecuado para algunos sitios web con un alto grado de diferenciación de módulos (personalmente creo que la diferenciación de módulos de sitios web grandes El grado generalmente es cada vez más alto).

La desventaja es la necesidad de cambiar la estructura DOM (el reemplazo y renderizado de los nodos DOM), lo que puede causar algunos reordenamientos y redibujados. Algunos usuarios que no habilitan la función js no verán el contenido de carga retrasada (puede usar la etiqueta noscript para dar un recordatorio amable). La mayor desventaja puede ser que no es propicio para el SEO. Algunos sitios web que se basan en SEO pueden necesitar trabajar duro en SEO, como Meituan.

En cuanto al SEO, puede consultar el sitio web http://www.seoqx.com/lynx , que puede simular el rastreo del sitio web por parte de las arañas de los motores de búsqueda. Meituan para BigRender y soluciones de SEO [caso de Meituan.com] Mejore los problemas de SEO causados ​​por la tecnología BigRender

bigrender acelera la representación de la primera pantalla al reducir los nodos DOM, pero también tiene una pérdida de rendimiento adicional. El código html en el área de texto antes de la representación se almacena en el área de texto oculta en el lado del servidor, por lo que se almacenará en el lado del servidor. Escape de código HTML: se han escapado los corchetes angulares, etc., esto aumentará la presión sobre el servidor; además, esta transformación es solo una representación de front-end, el servidor aún calcula todos los datos y genera todos los datos a la vez, esto no se ha mejorado.

En términos generales, el backend se empalma en cadenas html, luego se coloca en la etiqueta textarea y se escupe en el front end.

manifestación

Si desea hacer una demostración completa de BigRender, puede ser más complicado e involucrar al back-end.

Cuando estaba aprendiendo lazyload antes, hice una demostración de lazyloading de imágenes, consulte http://hanzichi.github.io/2015/picture-lazyload/. Debido a que BigRender es una versión mejorada de lazyload, simplemente hice una versión de BigRender de carga diferida de imágenes http://hanzichi.github.io/2016/bigrender/, el código específico se puede verificar https://github.com/hanzichi /hanzichi.github.io/blob/master/2016/bigrender/js/bigrender.js. Pide estrella, pide tenedor ~

otro

Además de usar textarea para la optimización de BigRender en la página de inicio, Meituan también usó etiquetas de script para la optimización. Por ejemplo, esta página de detalles del producto

Optimización del rendimiento del sitio web de alto tráfico: paso a paso para crear un complemento de BigRender adecuado

Establezca un tipo que no sea "text / javascript" para la etiqueta del script, puede descargar este js, pero no lo ejecute. Este enfoque parece familiar y se ha visto en labjs.

Para obtener más información, consulte la tercera continuación de la optimización del front-end: use un script para almacenar código html para reducir la cantidad de nodos DOM


Lee mas

  • Optimización de BigRender de la página de detalles de Taobao y la mejor manera de almacenar grandes cantidades de contenido HTML

  • Optimización de front-end: el área de texto de BigRender retrasó la representación y la práctica en LABjs

  • componentes de carga diferida de carga diferida

  • Aplicación de carga diferida de datos de carga diferida KISSY

  • kissy datalazyload.js código fuente

  • API de Kissy DataLazyload

  • Demostraciones de kissy DataLazyload

Supongo que te gusta

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