[Los pasantes de front-end se preparan para la contratación de otoño]: optimización del rendimiento de front-end, se recomienda recopilar

[Los pasantes de front-end se preparan para la contratación de otoño]: optimización del rendimiento de front-end, se recomienda recopilar

Preguntas de la entrevista sobre optimización del rendimiento.png

Directorio de artículos

1. CDN

1. El concepto de CDN

CDN (Content Delivery Network ) se refiere a un sistema de red informática conectado entre sí a través de Internet. Utiliza el servidor más cercano a cada usuario para entregar música, imágenes, vídeos, aplicaciones y otros archivos de forma más rápida y fiable. Enviar a los usuarios para proporcionar contenido de red de alto rendimiento, escalabilidad y bajo costo para los usuarios.

Un sistema CDN típico consta de las siguientes tres partes:

  • **Sistema de servicio de distribución:** La unidad de trabajo más básica es el dispositivo de caché, que es responsable de responder directamente a las solicitudes de acceso del usuario final y proporcionar rápidamente contenido almacenado en caché local a los usuarios. Al mismo tiempo, el caché también es responsable de la sincronización del contenido con el sitio de origen, obteniendo contenido actualizado y contenido que no está disponible localmente desde el sitio de origen y guardándolo localmente. El número, la escala y las capacidades de servicio total de los dispositivos de caché son los indicadores más básicos para medir las capacidades de servicio de un sistema CDN.
  • Sistema de equilibrio de carga: la función principal es programar el acceso a todos los usuarios que inician solicitudes de servicio y determinar la dirección de acceso real final proporcionada a los usuarios. El sistema de programación de dos niveles se divide en equilibrio de carga global (GSLB) y equilibrio de carga local (SLB). El equilibrio de carga global se basa principalmente en el principio de proximidad del usuario y determina la ubicación física del caché que proporciona servicios a los usuarios haciendo juicios "óptimos" sobre cada nodo de servicio. El equilibrio de carga local es el principal responsable del equilibrio de carga del dispositivo dentro del nodo.
  • Sistema de gestión de operaciones: el sistema de gestión de operaciones se divide en subsistemas de gestión de operaciones y gestión de redes y es responsable de manejar los trabajos de recolección, clasificación y entrega necesarios para la interacción con sistemas externos a nivel empresarial, incluida la gestión de clientes, gestión de productos y facturación. gestión, análisis estadístico, etc. Función.

2. El papel de CDN

Las CDN se utilizan generalmente para alojar recursos web (incluidos texto, imágenes, scripts, etc.), recursos descargables (archivos multimedia, software, documentos, etc.) y aplicaciones (portales, etc.). Utilice una CDN para acelerar el acceso a estos recursos.

(1) En términos de rendimiento, la función de introducir CDN es:

  • Los usuarios reciben contenido desde el centro de datos más cercano, con menor latencia y carga de contenido más rápida.
  • Algunas solicitudes de recursos se asignan a CDN, lo que reduce la carga en el servidor.

(2) En términos de seguridad, CDN ayuda a defenderse contra DDoS, MITM y otros ataques de red:

  • Para DDoS: monitoree y analice el tráfico anormal y limite su frecuencia de solicitud
  • Para MITM: comunicación HTTPS de enlace completo desde el servidor de origen al nodo CDN al ISP (proveedor de servicios de Internet)

Además, CDN, como servicio básico en la nube, también tiene ventajas en el alojamiento de recursos y la expansión bajo demanda (puede hacer frente a picos de tráfico).

3. Principios de CDN

CDN y DNS son inseparables. Primero echemos un vistazo al proceso de resolución de nombres de dominio de DNS. El proceso de resolución al ingresar www.test.com en el navegador es el siguiente:

(1) Verificar el caché del navegador

(2) Verifique el caché del sistema operativo, los más comunes, como el archivo de hosts

(3) Verificar el caché del enrutador

(4) Si no se encuentra en los primeros pasos, consultará el servidor LDNS del ISP (Proveedor de servicios de Internet)

(5) Si no se encuentra el servidor LDNS, solicitará resolución al servidor de nombres de dominio raíz (servidor raíz), que se divide en los siguientes pasos:

  • El servidor raíz devuelve la dirección del servidor de nombre de dominio de nivel superior (TLD), como .com, .cn, .orgetc. En este ejemplo, se devolverá .comla dirección
  • Luego envíe una solicitud al servidor de nombres de dominio de nivel superior y luego devuelva la dirección del servidor de nombres de dominio secundario (SLD). En este ejemplo, .testla dirección devuelta
  • Luego envíe una solicitud al servidor de nombres de dominio secundario y luego devuelva la IP de destino consultada a través del nombre de dominio. En este ejemplo, www.test.comla dirección devuelta
  • El servidor DNS local almacenará en caché los resultados y los devolverá al usuario, almacenados en caché en el sistema.

Cómo funciona CDN:

(1) El proceso de los usuarios que no utilizan CDN para almacenar en caché los recursos:

  1. El navegador resuelve el nombre de dominio a través de DNS (es decir, el proceso de resolución de DNS anterior) y obtiene a su vez la dirección IP correspondiente al nombre de dominio.
  2. El navegador envía una solicitud de datos al host del servicio del nombre de dominio en función de la dirección IP obtenida.
  3. El servidor devuelve datos de respuesta al navegador.

(2) El proceso de los usuarios que utilizan CDN para almacenar en caché recursos:

  1. Para la URL de los datos en los que se hizo clic, después del análisis por parte del sistema DNS local, se encuentra que la URL corresponde a un servidor DNS dedicado a CDN. El sistema DNS entregará los derechos de resolución de nombres de dominio al servidor DNS dedicado a CDN señalado por el CNAME.
  2. El servidor DNS dedicado de CND devuelve al usuario la dirección IP del dispositivo de equilibrio de carga global de CND.
  3. Los usuarios inician solicitudes de datos al dispositivo de equilibrio de carga global de CDN
  4. El dispositivo de equilibrio de carga global de la CDN selecciona un dispositivo de equilibrio de carga regional en la región del usuario en función de la dirección IP del usuario y la URL del contenido solicitada por el usuario, y le indica al usuario que inicie una solicitud a este dispositivo.
  5. El dispositivo de equilibrio de carga regional selecciona un servidor de caché adecuado para proporcionar servicios y devuelve la dirección IP del servidor de caché al dispositivo de equilibrio de carga global.
  6. El dispositivo de equilibrio de carga global devuelve la dirección IP del servidor al usuario
  7. El usuario inicia una solicitud al servidor de caché y el servidor de caché responde a la solicitud del usuario y envía el contenido requerido por el usuario al terminal del usuario.

Si el servidor de caché no tiene el contenido que el usuario desea, solicitará el contenido a su servidor de caché de nivel superior, y así sucesivamente, hasta que se obtengan los recursos necesarios. Al final, si todavía no existe, volverá a su propio servidor para obtener los recursos.

imagen

CNAME (que significa: alias): en la resolución de nombres de dominio, en realidad se analiza la dirección IP correspondiente al nombre de dominio especificado, o un CNAME del nombre de dominio, y luego se encuentra la dirección IP correspondiente en función de este CNAME.

4. Escenarios de uso de CDN

  • Utilice un servicio CDN de terceros. Si desea abrir algunos proyectos de código abierto, puede utilizar un servicio CDN de terceros.
  • Utilice CDN para almacenar en caché recursos estáticos y colocar los recursos estáticos de su sitio web en CDN, como js, ​​css, imágenes, etc. Todo el proyecto se puede colocar en CDN para completar la implementación con un solo clic.
  • Transmisión de transmisión en vivo La transmisión en vivo esencialmente utiliza medios de transmisión para la transmisión, y CDN también admite la transmisión de medios de transmisión, por lo que la transmisión en vivo puede usar CDN por completo para mejorar la velocidad de acceso. CDN procesa los medios de transmisión de manera diferente a los archivos estáticos comunes. Si no se encuentra un archivo común en el nodo de borde, irá a la capa superior para encontrarlo. Sin embargo, la cantidad de datos en los medios de transmisión en sí es muy grande. Utilice el método de regreso al código fuente inevitablemente provocará problemas de rendimiento, por lo que la transmisión de medios generalmente utiliza el envío activo.

2. Carga diferida

1. El concepto de carga diferida

La carga diferida, también llamada carga retrasada y carga bajo demanda, se refiere a retrasar la carga de datos de imágenes en páginas web largas y es una mejor manera de optimizar el rendimiento de la página web. En una página web o aplicación relativamente larga, si hay muchas imágenes, se cargarán todas y el usuario solo podrá ver esa parte de los datos de la imagen en la ventana visual, lo que desperdicia rendimiento.

Si utiliza la carga diferida de imágenes, puede resolver el problema anterior. Las imágenes fuera del área visual no se cargarán antes de que se desplace la pantalla y solo se cargarán cuando se desplace la pantalla. Esto hace que las páginas web se carguen más rápido y reduce la carga en el servidor. La carga diferida es adecuada para escenarios donde hay muchas imágenes y una lista de páginas larga (lista larga).

2. Características de la carga diferida

  • Reducir la carga de recursos inútiles : el uso de carga diferida reduce significativamente la presión y el tráfico en el servidor, y también reduce la carga en el navegador.
  • Mejore la experiencia del usuario : si carga más imágenes al mismo tiempo, es posible que deba esperar más tiempo, lo que afecta la experiencia del usuario. El uso de la carga diferida puede mejorar enormemente la experiencia del usuario.
  • Evite que la carga de demasiadas imágenes afecte la carga de otros archivos de recursos : esto afectará el uso normal de las aplicaciones del sitio web.

3. Principio de implementación de la carga diferida.

La carga de imágenes es srccausada por: Cuando srcse asigna un valor, el navegador solicitará el recurso de imagen. Con base en este principio, utilizamos data-xxxatributos HTML5 para almacenar la ruta de la imagen. Cuando necesitamos cargar la imagen, asignamos data-xxxla ruta a la imagen src. Esto logra la carga de imágenes bajo demanda, es decir, carga diferida.

Nota: data-xxxse xxxpuede personalizar, aquí usamos data-srcpara definir.

El punto clave de la implementación de la carga diferida es determinar qué imagen necesita cargar el usuario. En el navegador, los recursos en el área visible son los recursos que el usuario necesita. Entonces, cuando la imagen aparezca en el área visible, simplemente obtenga la dirección real de la imagen y asígnela a la imagen.

Utilice JavaScript nativo para implementar la carga diferida:

Puntos de conocimiento:

(1) window.innerHeightes la altura del área visual del navegador

(2) document.body.scrollTop || document.documentElement.scrollTopEs la distancia que recorre el navegador.

(3) imgs.offsetTopes la altura desde la parte superior del elemento hasta la parte superior del documento (incluida la distancia de la barra de desplazamiento)

(4) Condiciones de carga de imágenes:img.offsetTop < window.innerHeight + document.body.scrollTop;

Ilustración:

imagen

Código:

<div class="container">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
</div>
<script>
var imgs = document.querySelectorAll('img');
function lozyLoad(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        var winHeight= window.innerHeight;
        for(var i=0;i < imgs.length;i++){
            if(imgs[i].offsetTop < scrollTop + winHeight ){
                imgs[i].src = imgs[i].getAttribute('data-src');
            }
        }
    }
  window.onscroll = lozyLoad();
</script>

4. La diferencia entre carga diferida y precarga

Ambos métodos son formas de mejorar el rendimiento de las páginas web. La principal diferencia entre los dos es que uno se carga temprano y el otro se carga lentamente o incluso no se carga en absoluto. La carga diferida tiene cierto efecto al aliviar la presión en la interfaz del servidor, mientras que la precarga aumentará la presión en la interfaz del servidor.

  • La carga diferida también se llama carga retrasada. Se refiere al retraso en la carga de imágenes en páginas web largas. Cuando los usuarios necesitan acceder a ellas, se cargarán nuevamente. Esto puede mejorar la velocidad de carga de la primera pantalla del sitio web, mejorar la experiencia del usuario y reducir la carga en el servidor. Es adecuado para sitios web de comercio electrónico con muchas imágenes y páginas largas. El principio de implementación de la carga diferida es establecer el atributo src de la imagen en la página en una cadena vacía, guardar la ruta real de la imagen en un atributo personalizado y, cuando la página se desplaza, se juzgará si la imagen ingresa al área visible de la página. Dentro, la ruta real se toma del atributo personalizado y se asigna al atributo src de la imagen para lograr una carga diferida de la imagen.
  • La precarga se refiere a solicitar que los recursos necesarios se carguen localmente con anticipación, de modo que los recursos se puedan recuperar directamente del caché cuando sea necesario más adelante. La precarga puede reducir el tiempo de espera del usuario y mejorar la experiencia del usuario. La forma más común que conozco sobre la precarga es usar el objeto de imagen en js y establecer el atributo scr del objeto de imagen para lograr la precarga de la imagen.

3. Refluir y volver a dibujar

1. Conceptos y condiciones desencadenantes de reflujo y redibujo

(1) Reflujo

Cuando el tamaño, la estructura o los atributos de algunos o todos los elementos del árbol de renderizado cambian, el proceso en el que el navegador vuelve a renderizar parte o la totalidad del documento se llama reflujo .

Las siguientes operaciones pueden provocar reflujo:

  • Primera representación de la página.
  • El tamaño de la ventana del navegador cambia.
  • El contenido del elemento cambia.
  • El tamaño o posición del elemento cambia.
  • El tamaño de fuente de un elemento cambia.
  • Activar pseudoclases CSS
  • Consultar algunas propiedades o llamar a algunos métodos.
  • Agregar o eliminar elementos DOM visibles

Cuando se activa el reflujo (reorganización), dado que el navegador representa la página según un diseño fluido, cuando se activa el reflujo, los elementos DOM circundantes se reorganizarán. Su alcance de influencia es de dos tipos:

  • Alcance global: retransmisión de todo el árbol de renderizado comenzando desde el nodo raíz
  • Alcance local: retransmitir una determinada parte del árbol de renderizado o un objeto de renderizado

(2) Redibujar

Cuando el estilo de algunos elementos en la página cambia, pero no afecta su posición en el flujo de documentos, el navegador volverá a dibujar los elementos, este proceso se llama redibujar .

Las siguientes operaciones pueden provocar reflujo:

  • Color, propiedades relacionadas con el fondo: color de fondo, imagen de fondo, etc.
  • atributos relacionados con el contorno: color del contorno, ancho del contorno, decoración del texto
  • radio de borde, visibilidad, sombra de caja

Nota: Cuando se activa el reflujo, definitivamente se activará el redibujo, pero el redibujo no necesariamente activa el reflujo.

2. ¿Cómo evitar el reflujo y el redibujado?

Medidas para reducir el reflujo y volver a dibujar:

  • Cuando opere DOM, intente operar en nodos DOM de bajo nivel.
  • No utilice tablediseños, un pequeño cambio puede hacer que tablese modifique el diseño completo.
  • Expresiones usando CSS
  • No manipule con frecuencia el estilo de los elementos. Para páginas estáticas, puede modificar el nombre de la clase en lugar del estilo.
  • Utilice absoluto o fijo para eliminar elementos del flujo de documentos de modo que los cambios en ellos no afecten a otros elementos.
  • Para evitar manipular con frecuencia el DOM, puede crear un fragmento de documento documentFragment, aplicarle todas las operaciones DOM y finalmente agregarlo al documento.
  • Configure el elemento primero display: noney luego muéstrelo una vez completada la operación. Porque las operaciones DOM realizadas en elementos con un atributo de visualización ninguno no provocarán reflujo ni redibujo.
  • Junte varias operaciones de lectura (u operaciones de escritura) del DOM en lugar de intercalar operaciones de lectura y escritura con escrituras. Esto se debe al mecanismo de cola de procesamiento del navegador .

El navegador se ha optimizado para redistribuir y redibujar la página: cola de procesamiento

El navegador pondrá todas las operaciones de reflujo y redibujo en una cola. Cuando las operaciones en la cola alcancen un cierto número o un cierto intervalo de tiempo, el navegador agrupará la cola. Esto convertirá múltiples reflujos y redibujados en un solo reflujo y redibujado.

Arriba, cuando se juntan varias operaciones de lectura (u operaciones de escritura), se ejecutarán después de que todas las operaciones de lectura ingresen a la cola, de esta manera, en lugar de activar múltiples reflujos, solo se activa uno.

3. ¿Cómo optimizar la animación?

En cuanto a cómo optimizar la animación, sabemos que, en general, la animación requiere manipulación DOM frecuente, lo que causará problemas de rendimiento en la página. Podemos establecer las propiedades de la animación o separar la animación positiondel absoluteflujo fixeddel documento, para que su reflujo No afectará a la página.

4. ¿Qué es el fragmento de documento? ¿Cuál es la diferencia entre usarlo y manipular directamente el DOM?

Explicación de MDN documentFragmentde:

DocumentFragment, interfaz de fragmento de documento, un objeto de documento mínimo sin un objeto principal. Se utiliza como una versión ligera de Document, al igual que un documento estándar, y almacena una estructura de documento compuesta de nodos. En comparación con el documento, la mayor diferencia es que DocumentFragment no es parte del árbol DOM real, sus cambios no activarán la repetición del árbol DOM y no causarán problemas de rendimiento ni de otro tipo.

Cuando insertamos un nodo DocumentFragment en el árbol de documentos, lo que se inserta no es el DocumentFragment en sí, sino todos sus nodos descendientes. Durante las operaciones DOM frecuentes, podemos insertar elementos DOM en DocumentFragment y luego insertar todos los nodos descendientes en el documento a la vez. En comparación con operar directamente el DOM, insertar un nodo DocumentFragment en el árbol DOM no provocará que se vuelva a dibujar la página, lo que mejora enormemente el rendimiento de la página.

4. Estrangulamiento y antivibración

1. Comprensión de la aceleración y la antivibración.

  • La función anti-vibración significa ejecutar la devolución de llamada n segundos después de que se activa el evento. Si el evento se activa nuevamente dentro de estos n segundos, el tiempo se reiniciará. Esto se puede usar en algunos eventos de solicitud de clic para evitar enviar múltiples solicitudes al backend debido a varios clics de los usuarios.
  • La limitación de funciones se refiere a especificar una unidad de tiempo. Dentro de esta unidad de tiempo, la función de devolución de llamada que activa el evento solo se puede ejecutar una vez. Si un evento se activa varias veces en la misma unidad de tiempo, solo una vez puede tener efecto. La limitación se puede utilizar en la escucha de eventos de la función de desplazamiento para reducir la frecuencia de las llamadas a eventos mediante la limitación de eventos.

Escenarios de aplicación de la función antivibración:

  • Escenario de envío de botones: evite el envío de múltiples botones y solo ejecute el último envío
  • Escenario de verificación del lado del servidor: la verificación del formulario requiere la cooperación del servidor. Solo se ejecuta la última vez de un evento de entrada continuo. También hay una función de búsqueda similar para palabras asociadas en el entorno de vida. Utilice lodash.debounce.

Los escenarios más aplicables para funciones de limitación:

  • Escenario de arrastrar y soltar: solo se ejecuta una vez dentro de un período de tiempo fijo para evitar que se activen cambios de posición excesivamente frecuentes.
  • Escenario de zoom: supervisar el cambio de tamaño del navegador
  • Escena de animación: evite problemas de rendimiento causados ​​por activar la animación varias veces en un corto período de tiempo

2. Implementar la función de aceleración y la función antivibración.

Implementación de la función antivibración:

function debounce(fn, wait) {
  var timer = null;

  return function() {
    var context = this,
      args = [...arguments];

    // 如果此时存在定时器的话,则取消之前的定时器重新记时
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    // 设置定时器,使事件间隔指定事件后执行
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, wait);
  };
}

Implementación de la función de limitación:

// 时间戳版
function throttle(fn, delay) {
  var preTime = Date.now();

  return function() {
    var context = this,
      args = [...arguments],
      nowTime = Date.now();

    // 如果两次时间间隔超过了指定时间,则执行函数。
    if (nowTime - preTime >= delay) {
      preTime = Date.now();
      return fn.apply(context, args);
    }
  };
}

// 定时器版
function throttle (fun, wait){
  let timeout = null
  return function(){
    let context = this
    let args = [...arguments]
    if(!timeout){
      timeout = setTimeout(() => {
        fun.apply(context, args)
        timeout = null 
      }, wait)
    }
  }
}

5. Optimización de imágenes

1. ¿Cómo optimizar las imágenes del proyecto?

  1. No se necesitan fotografías. Muchas veces se utilizan muchas imágenes modificadas, de hecho, estas imágenes modificadas pueden ser reemplazadas por CSS.
  2. Para los dispositivos móviles, el ancho de la pantalla es tan pequeño, por lo que no hay necesidad de desperdiciar ancho de banda cargando la imagen original. Generalmente, las imágenes se cargan mediante CDN, que puede calcular el ancho para ajustarse a la pantalla y luego solicitar la imagen recortada correspondiente.
  3. Las imágenes pequeñas utilizan el formato base64.
  4. Consolidar varios archivos de iconos en una sola imagen (imagen de Sprite)
  5. Elija el formato de imagen correcto:
    • Para los navegadores que pueden mostrar el formato WebP, intente utilizar el formato WebP. Debido a que el formato WebP tiene un mejor algoritmo de compresión de datos de imagen, puede reducir el tamaño de la imagen y su calidad de imagen es indistinguible a simple vista. La desventaja es que la compatibilidad no es buena.
    • Las imágenes pequeñas usan PNG. De hecho, para la mayoría de los íconos y otras imágenes, se puede usar SVG.
    • Fotos usando JPEG

2. Formatos de imagen comunes y escenarios de uso.

(1) BMP es un mapa de bits sin pérdidas que admite colores directos y indexados. Este formato de imagen casi no realiza compresión de datos, por lo que las imágenes en formato BMP suelen ser archivos más grandes.

(2) GIF es un mapa de bits sin pérdidas que utiliza colores indexados. Codificado utilizando el algoritmo de compresión LZW. El tamaño de archivo pequeño es la ventaja del formato GIF, al mismo tiempo que el formato GIF también tiene la ventaja de admitir animación y transparencia. Sin embargo, el formato GIF solo admite colores indexados de 8 bits, por lo que el formato GIF es adecuado para escenas que no tienen requisitos de color elevados y requieren un tamaño de archivo pequeño.

(3) JPEG es un mapa de bits de color directo y con pérdida. La ventaja de las imágenes JPEG es que utilizan colores directos. Gracias a sus colores más ricos, JPEG es muy adecuado para almacenar fotografías. En comparación con GIF, JPEG no es adecuado para almacenar logotipos corporativos e imágenes de estructura alámbrica. Porque la compresión con pérdida hará que la imagen se vea borrosa y la selección de colores directos hará que el archivo de imagen sea más grande que GIF.

(4) PNG-8 es un mapa de bits sin pérdidas que utiliza colores indexados. PNG es un formato de imagen relativamente nuevo y PNG-8 es un muy buen sustituto del formato GIF. Cuando sea posible, se debe utilizar PNG-8 en lugar de GIF, porque bajo el mismo efecto de imagen, PNG-8 tiene un tamaño de archivo más pequeño. Además, PNG-8 también admite el ajuste de transparencia, mientras que GIF no. A menos que se requiera soporte para animación, no hay razón para usar GIF en lugar de PNG-8.

(5) PNG-24 es un mapa de bits sin pérdidas que utiliza color directo. La ventaja de PNG-24 es que comprime los datos de la imagen, lo que hace que el tamaño del archivo del formato PNG-24 sea mucho más pequeño que el de BMP para lograr el mismo efecto. Por supuesto, las imágenes PNG24 siguen siendo mucho más grandes que JPEG, GIF y PNG-8.

(6) SVG es una imagen vectorial sin pérdidas. SVG es un gráfico vectorial, lo que significa que una imagen SVG consta de líneas rectas y curvas y un método para dibujarlas. Cuando haces zoom en una imagen SVG, todavía ves líneas y curvas, pero no píxeles. Esto significa que las imágenes SVG no se distorsionarán cuando se amplíen, por lo que es muy adecuado para dibujar logotipos, iconos, etc.

(7) WebP es un nuevo formato de imagen desarrollado por Google. WebP es un mapa de bits que admite compresión con y sin pérdida y utiliza color directo. Del nombre se desprende que nace para la Web ¿Qué significa nacer para la Web? Es decir, para imágenes de la misma calidad, WebP tiene un tamaño de archivo menor. Hoy en día, los sitios web están llenos de una gran cantidad de imágenes. Si se puede reducir el tamaño del archivo de cada imagen, la cantidad de transmisión de datos entre el navegador y el servidor se reducirá considerablemente, lo que reducirá el retraso de acceso y mejorará la experiencia de acceso. Actualmente, sólo el navegador Chrome y el navegador Opera admiten el formato WebP y la compatibilidad no es muy buena.

  • En el caso de la compresión sin pérdidas, el tamaño de archivo de imágenes WebP de la misma calidad es un 26% más pequeño que el de PNG;
  • En el caso de la compresión con pérdida, el tamaño del archivo de las imágenes WebP con la misma precisión de imagen es entre un 25% y un 34% más pequeño que el de JPEG;
  • El formato de imagen WebP admite la transparencia de la imagen. Una imagen WebP comprimida sin pérdidas requiere solo el 22 % del tamaño del archivo adicional para admitir la transparencia.

6. Optimización del paquete web

1. ¿Cómo mejorar la velocidad de empaquetado de webpack?

(1) Optimizar el cargador

Para Loader, Babel debe soportar la peor parte del impacto en la eficiencia del embalaje. Debido a que Babel convertirá el código en una cadena para generar un AST, luego continuará transformando el AST y finalmente generará un nuevo código. Cuanto más grande sea el proyecto, más código se convertirá y menor será la eficiencia . Por supuesto, esto se puede optimizar.

Primero, optimizamos el rango de búsqueda de archivos de Loader.

module.exports = {
  module: {
    rules: [
      {
        // js 文件才使用 babel
        test: /\.js$/,
        loader: 'babel-loader',
        // 只在 src 文件夹下查找
        include: [resolve('src')],
        // 不会去查找的路径
        exclude: /node_modules/
      }
    ]
  }
}

Para Babel, espero que solo funcione en código JS y que node_modulesel código utilizado esté compilado, por lo que no es necesario procesarlo nuevamente.

Por supuesto, esto no es suficiente, también puede almacenar en caché los archivos compilados por Babel . La próxima vez, solo necesitará compilar los archivos de código modificados, lo que puede acelerar enormemente el tiempo de empaquetado.

loader: 'babel-loader?cacheDirectory=true'

(2) Paquete feliz

Debido al hecho de que Node se ejecuta en un solo subproceso, Webpack también se ejecuta en un solo subproceso durante el proceso de empaquetado. Especialmente cuando se ejecuta el cargador, hay muchas tareas de compilación a largo plazo, lo que provocará esperas.

HappyPack puede convertir la ejecución sincrónica de Loader en paralela , de modo que los recursos del sistema se puedan utilizar por completo para acelerar la eficiencia del empaquetado.

module: {
  loaders: [
    {
      test: /\.js$/,
      include: [resolve('src')],
      exclude: /node_modules/,
      // id 后面的内容对应下面
      loader: 'happypack/loader?id=happybabel'
    }
  ]
},
plugins: [
  new HappyPack({
    id: 'happybabel',
    loaders: ['babel-loader?cacheDirectory'],
    // 开启 4 个线程
    threads: 4
  })
]

(3)Complemento Dll

DllPlugin puede empaquetar bibliotecas de clases específicas por adelantado y luego presentarlas . Este método puede reducir en gran medida la cantidad de veces que se empaqueta la biblioteca de clases. Solo cuando la biblioteca de clases se actualiza es necesario volver a empaquetarla y también implementa la solución de optimización de extraer código público en archivos separados. El modo de utilizar DllPlugin es el siguiente:

// 单独配置在一个文件中
// webpack.dll.conf.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
  entry: {
    // 想统一打包的类库
    vendor: ['react']
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].dll.js',
    library: '[name]-[hash]'
  },
  plugins: [
    new webpack.DllPlugin({
      // name 必须和 output.library 一致
      name: '[name]-[hash]',
      // 该属性需要与 DllReferencePlugin 中一致
      context: __dirname,
      path: path.join(__dirname, 'dist', '[name]-manifest.json')
    })
  ]
}

Luego debe ejecutar este archivo de configuración para generar archivos de dependencia, y luego debe DllReferencePluginintroducir los archivos de dependencia en el proyecto usando

// webpack.conf.js
module.exports = {
  // ...省略其他配置
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      // manifest 就是之前打包出来的 json 文件
      manifest: require('./dist/vendor-manifest.json'),
    })
  ]
}

(4) Compresión de código

En Webpack3, generalmente se usa UglifyJSpara comprimir código, pero esto se ejecuta en un solo hilo. Para acelerar la eficiencia, puede usarlo webpack-parallel-uglify-pluginpara ejecutar en paralelo UglifyJS, mejorando así la eficiencia.

En Webpack4, estas operaciones ya no son necesarias, solo necesita modeconfigurar productionpara habilitar las funciones anteriores de forma predeterminada. La compresión de código también es una solución de optimización del rendimiento imprescindible para nosotros. Por supuesto, no solo podemos comprimir código JS, sino también código HTML y CSS. En el proceso de comprimir código JS, también podemos implementar funciones como eliminar dicho código. a través de la configuración console.log.

(5) Otros

La velocidad de empaquetado se puede acelerar mediante algunos pequeños puntos de optimización

  • resolve.extensions: Se utiliza para indicar la lista de sufijos de archivos. El orden de búsqueda predeterminado es ['.js', '.json']. Si su archivo importado no agrega un sufijo, los archivos se buscarán en este orden. Deberíamos reducir la longitud de la lista de sufijos tanto como sea posible y luego clasificar los sufijos con alta frecuencia al principio.
  • resolve.alias: Puede asignar una ruta a través de un alias, lo que permite que Webpack encuentre la ruta más rápido.
  • module.noParse: Si está seguro de que no hay otras dependencias en un archivo, puede usar este atributo para evitar que Webpack escanee el archivo. Este método es muy útil para bibliotecas de clases grandes.

2. Cómo reducir el tamaño del paquete Webpack

(1) Carga bajo demanda

Al desarrollar un proyecto SPA, habrá muchas páginas de enrutamiento en el proyecto. Si todas estas páginas se empaquetan en un archivo JS, aunque se fusionen varias solicitudes, también se cargará una gran cantidad de código innecesario, lo que llevará más tiempo. Para que la página de inicio se presente a los usuarios más rápido, se espera que el tamaño del archivo que se puede cargar en la página de inicio sea lo más pequeño posible. En este momento, puede utilizar la carga bajo demanda para empaquetar cada enrutamiento. página en un archivo separado . Por supuesto, no solo se pueden cargar rutas bajo demanda, loadashesta función también se puede utilizar para bibliotecas de clases tan grandes.

La implementación del código de carga bajo demanda no se discutirá en detalle aquí porque la implementación es diferente debido a los diferentes marcos utilizados. Por supuesto, aunque su uso puede ser diferente, el mecanismo subyacente es el mismo. Cuando se usa, se descarga el archivo correspondiente y se devuelve uno Promise. Cuando Promisetiene éxito, se ejecuta la devolución de llamada.

(2) Elevación del alcance

Scope Hoisting analizará las dependencias entre módulos y fusionará los módulos empaquetados en una sola función tanto como sea posible.

Por ejemplo, si desea empaquetar dos archivos:

// test.js
export const a = 1
// index.js
import { a } from './test.js'

En este caso, el código empaquetado se verá así:

[
  /* 0 */
  function (module, exports, require) {
    //...
  },
  /* 1 */
  function (module, exports, require) {
    //...
  }
]

Pero si usa Scope Hoisting, el código se fusionará en una función tanto como sea posible y será similar a este código:

[
  /* 0 */
  function (module, exports, require) {
    //...
  }
]

El código generado por este método de empaquetado es obviamente mucho menor que antes. Si desea habilitar esta función en Webpack 4, simplemente habilítela optimization.concatenateModules:

module.exports = {
  optimization: {
    concatenateModules: true
  }
}

(3) Sacudida de árboles

Tree Shaking puede eliminar código sin referencia en el proyecto , como:

// test.js
export const a = 1
export const b = 2
// index.js
import { a } from './test.js'

Para la situación anterior, testlas variables del archivo bno se empaquetarán en el archivo si no se utilizan en el proyecto.

Si utiliza Webpack 4, esta función de optimización se activará automáticamente cuando abra el entorno de producción.

3. ¿Cómo utilizar webpack para optimizar el rendimiento del front-end?

Usar webpack para optimizar el rendimiento del front-end significa optimizar la salida de webpack para que el resultado final empaquetado se ejecute de manera rápida y eficiente en el navegador.

  • Comprimir código : eliminar código redundante, comentarios, simplificar la escritura de código, etc. Puede usar UglifyJsPlugin y ParallelUglifyPlugin del paquete web para comprimir archivos JS y usar cssnano (css-loader?minimize) para comprimir css.
  • Utilice la aceleración de CDN : durante el proceso de compilación, modifique la ruta del recurso estático a la que se hace referencia a la ruta correspondiente en la CDN. Puede utilizar el parámetro de salida del paquete web y el parámetro publicPath de cada cargador para modificar la ruta del recurso.
  • Tree Shaking : elimina secciones de código que nunca se verán. Esto se puede lograr agregando el parámetro --optimize-minimize al iniciar el paquete web
  • División de código: divida el código en fragmentos según las dimensiones o componentes del enrutamiento, de modo que pueda cargarse según demanda y la memoria caché del navegador pueda utilizarse por completo.
  • Extraiga bibliotecas públicas de terceros : complemento SplitChunksPlugin para extraer módulos públicos y utilice el caché del navegador para almacenar en caché estos códigos públicos que no necesitan cambiar con frecuencia durante mucho tiempo.

4. ¿Cómo mejorar la velocidad de compilación del paquete web ?

  1. En el caso de varias entradas, utilice CommonsChunkPlugin para extraer código común
  2. Extraiga bibliotecas comunes a través de configuración externa
  3. Utilice los módulos de recursos precompilados DllPlugin y DllReferencePlugin para precompilar los paquetes npm a los que hacemos referencia pero que nunca modificaremos a través de DllPlugin, y luego cargue los módulos precompilados a través de DllReferencePlugin.
  4. Utilice Happypack para lograr una compilación acelerada de subprocesos múltiples
  5. Utilice webpack-uglify-parallel para mejorar la velocidad de compresión de uglifyPlugin. En principio, webpack-uglify-parallel utiliza compresión paralela de múltiples núcleos para mejorar la velocidad de compresión y
    el parámetro publicPath del cargador se utiliza para modificar la ruta del recurso.
  • Tree Shaking : elimina secciones de código que nunca se verán. Esto se puede lograr agregando el parámetro --optimize-minimize al iniciar el paquete web
  • División de código: divida el código en fragmentos según las dimensiones o componentes del enrutamiento, de modo que pueda cargarse según demanda y la memoria caché del navegador pueda utilizarse por completo.
  • Extraiga bibliotecas públicas de terceros : complemento SplitChunksPlugin para extraer módulos públicos y utilice el caché del navegador para almacenar en caché estos códigos públicos que no necesitan cambiar con frecuencia durante mucho tiempo.

4. ¿Cómo mejorar la velocidad de compilación del paquete web ?

  1. En el caso de varias entradas, utilice CommonsChunkPlugin para extraer código común
  2. Extraiga bibliotecas comunes a través de configuración externa
  3. Utilice los módulos de recursos precompilados DllPlugin y DllReferencePlugin para precompilar los paquetes npm a los que hacemos referencia pero que nunca modificaremos a través de DllPlugin, y luego cargue los módulos precompilados a través de DllReferencePlugin.
  4. Utilice Happypack para lograr una compilación acelerada de subprocesos múltiples
  5. Utilice webpack-uglify-parallel para mejorar la velocidad de compresión de uglifyPlugin. En principio, webpack-uglify-parallel utiliza compresión paralela de múltiples núcleos para mejorar la velocidad de compresión.
  6. Utilice Tree-Shaking y Scope Hoisting para eliminar el código redundante

Supongo que te gusta

Origin blog.csdn.net/m0_46374969/article/details/132455539
Recomendado
Clasificación