Reduce y comprime las cargas útiles de red con gzip

En este codelab, se explora cómo reducir y comprimir JavaScript para la siguiente aplicación mejora el rendimiento de la página reduciendo el tamaño de la solicitud de la app.

Captura de pantalla de la app

Medir

Antes de comenzar a agregar optimizaciones, siempre es buena idea analizar primero el estado actual de la aplicación.

  • Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa pantalla completa

Esta app, que también se incluyó en la sección "Cómo quitar "code", te permite votar por tu gatito. 🐈

Ahora, observa el tamaño de esta aplicación:

  1. Presiona `Control + Mayúsculas + J` (o `Command + Option + J` en Mac) para abrir Herramientas para desarrolladores.
  2. Haga clic en la pestaña Red.
  3. Selecciona la casilla de verificación Inhabilitar caché.
  4. Vuelve a cargar la app.

Tamaño original del paquete en el panel Red

Si bien hubo mucho progreso en la sección "Quita el código que no se usa" para reducir el tamaño de este paquete, 225 KB aún es bastante grande.

Reducción

Considera el siguiente bloque de código.

function soNice() {
  let counter = 0;

  while (counter < 100) {
    console.log('nice');
    counter++;
  }
}

Si esta función se guarda en un archivo propio, el tamaño del archivo es de aproximadamente 112 B (bytes).

Si se quitan todos los espacios en blanco, el código resultante se verá de la siguiente manera:

function soNice(){let counter=0;while(counter<100){console.log("nice");counter++;}}

Ahora, el tamaño del archivo será de alrededor de 83 B. Si se complica aún más disminuyendo la longitud del nombre de la variable y la modificación de algunas expresiones, el código final puede terminar luciendo así:

function soNice(){for(let i=0;i<100;)console.log("nice"),i++}

El tamaño del archivo ahora alcanza 62 B.

Con cada paso, el código es cada vez más difícil de leer. Sin embargo, la configuración del navegador El motor de JavaScript los interpreta de la misma manera. El de ofuscar el código de esta manera puede ayudar a lograr una configuración de tamaños. En realidad, 112 B no era mucho al principio, pero aún había un 50% con reducción de tamaño.

En esta aplicación, se usa la versión 4 de webpack como agrupador de módulos. La versión específica se puede ver en package.json.

"devDependencies": {
  //...
  "webpack": "^4.16.4",
  //...
}

La versión 4 ya reduce el paquete de forma predeterminada durante el modo de producción. Utiliza TerserWebpackPlugin es un complemento para Terser. Terser es una herramienta popular que se usa para comprimir código JavaScript.

Para tener una idea de cómo se ve el código reducido, haz clic en main.bundle.js en el panel Red de Herramientas para desarrolladores. Ahora haz clic en Pestaña Respuesta.

Respuesta reducida

El código en su forma final, reducida y moldeada, se muestra en el cuerpo de la respuesta. Para averiguar qué tan grande podría haber sido el paquete si no se redujo, abre webpack.config.js y actualiza la configuración de mode.

module.exports = {
  mode: 'production',
  mode: 'none',
  //...

Vuelve a cargar la aplicación y observa nuevamente el tamaño del paquete en la Panel Red de Herramientas para desarrolladores

El tamaño del paquete es de 767 KB.

¡Es una gran diferencia! 😅

Asegúrate de revertir los cambios aquí antes de continuar.

module.exports = {
  mode: 'production',
  mode: 'none',
  //...

La inclusión de un proceso para reducir el código en tu aplicación depende de las herramientas que usas:

  • Si se usa webpack v4 o superior, no es necesario realizar ninguna acción adicional. ya que el código se reduce de forma predeterminada en el modo de producción. 👍
  • Si usas una versión anterior de webpack, instala TerserWebpackPlugin y, luego, inclúyelo. en el proceso de compilación del paquete web. La documentación explica esto en detalle.
  • También existen otros complementos de reducción que se pueden usar en su lugar. como BabelMinifyWebpackPlugin. y ClosureCompilerPlugin.
  • Si no se usa un agrupador de módulos en absoluto, usa Terser como una herramienta de la CLI o incluirlo directamente como una dependencia.

Compresión

Aunque el término "compresión" a veces se usa vagamente para explicar cómo se durante el proceso de reducción, no se comprime en el literal.

Por lo general, la compresión se refiere al código que se modificó con un de compresión. A diferencia de la reducción, que termina proporcionando información código válido, se debe descomprimir el código comprimido antes de utilizarlo.

Con cada solicitud y respuesta HTTP, los navegadores y servidores web pueden agregar headers que se deben incluir información adicional sobre el activo que se recupera o recibe. Puede ser que se ve en la pestaña Headers del panel de red de Herramientas para desarrolladores, donde tres tipos se muestran los siguientes datos:

  • General representa encabezados generales relevantes para toda la solicitud-respuesta. interacción.
  • Encabezados de respuesta muestra una lista de encabezados específicos de la respuesta real. del servidor.
  • En Encabezados de solicitud, se muestra una lista de encabezados adjuntos a la solicitud por parte de la cliente.

Observa el encabezado accept-encoding en el Request Headers.

Aceptar encabezado de codificación

El navegador usa accept-encoding para especificar qué contenido o algoritmos de compresión, admite. Existen muchas de compresión de texto, pero solo hay tres Se admite aquí para la compresión (y descompresión) de las solicitudes de red HTTP:

  • Gzip (gzip): La compresión más usada para las interacciones entre el servidor y el cliente. Se basa en la disminución del rendimiento. y es compatible con todos los navegadores actuales.
  • Reducción (deflate): no se usa con frecuencia.
  • Brotli (br): Una compresión más reciente. algoritmo que busca mejorar aún más las proporciones de compresión, lo que puede generar las páginas se carguen más rápido. Se admite en el las versiones más recientes de la mayoría de los navegadores.

La aplicación de ejemplo de este instructivo es idéntica a la aplicación completada en el "Quita el código que no se usa", excepto por el hecho de que Express ahora se usa como framework del servidor. En la próxima se exploran algunas secciones, tanto la compresión estática como la dinámica.

Compresión dinámica

La compresión dinámica implica comprimir recursos sobre la marcha a medida que se que solicita el navegador.

Ventajas

  • Crear y actualizar versiones comprimidas guardadas de los recursos no tiene por qué listo.
  • La compresión sobre la marcha funciona especialmente bien para las páginas web que generados de forma dinámica.

Desventajas

  • Comprimir archivos en niveles más altos para lograr mejores relaciones de compresión tarda más. Esto puede provocar un hit de rendimiento mientras el usuario espera a que los recursos comprimir antes de que el servidor los envíe.

Compresión dinámica con Node/Express

El archivo server.js se encarga de configurar el servidor de Node que aloja la aplicación.

const express = require('express');

const app = express();

app.use(express.static('public'));

const listener = app.listen(process.env.PORT, function() {
  console.log('Your app is listening on port ' + listener.address().port);
});

Todo lo que hace actualmente es importar express y usar express.static middleware para cargar todos los archivos HTML, JS y CSS estáticos en la Directorio public/ (y Webpack crea esos archivos con cada compilación).

Para asegurarse de que todos los recursos se compriman cada vez que se soliciten, el Compresion de middleware que se usará. Primero, agrégalo como devDependency en package.json:

"devDependencies": {
  //...
  "compression": "^1.7.3"
},

Luego, impórtalo al archivo del servidor, server.js:

const express = require('express');
const compression = require('compression');

Y agrégalo como middleware antes de que se active express.static:

//...

const app = express();

app.use(compression());

app.use(express.static('public'));

//...

Ahora, vuelve a cargar la app y observa el tamaño del paquete en el panel Red.

Tamaño del paquete con compresión dinámica

De 225 KB a 61.6 KB. En el Response Headers, ahora, una content-encoding muestra que el servidor está enviando este archivo codificado con gzip.

Encabezado de codificación de contenido

Compresión estática

La idea detrás de la compresión estática es comprimir y guardar los recursos con anticipación.

Ventajas

  • La latencia debido a los altos niveles de compresión ya no es un problema. No es necesario que ocurra nada sobre la marcha para comprimir los archivos, ya que ahora se pueden recuperar directamente.

Desventajas

  • Los recursos deben comprimirse con cada compilación. Los tiempos de compilación pueden aumentar si se usan altos niveles de compresión.

Compresión estática con Node/Express y webpack

Dado que la compresión estática implica comprimir archivos por adelantado, webpack de Terraform para comprimir los recursos como parte del paso de compilación. CompressionPlugin para ello.

Primero, agrégalo como devDependency en package.json:

"devDependencies": {
  //...
  "compression-webpack-plugin": "^1.1.11"
},

Como cualquier otro complemento webpack, impórtalo en el archivo de configuración, webpack.config.js:

const path = require("path");

//...

const CompressionPlugin = require("compression-webpack-plugin");

Inclúyela en el array plugins:

module.exports = {
  //...
  plugins: [
    //...
    new CompressionPlugin()
  ]
}

De forma predeterminada, el complemento comprime los archivos de compilación con gzip. Echar un vistazo en la documentación para aprender a agregar opciones y usar un algoritmo diferente o incluir o excluir determinados archivos.

Cuando la app se vuelve a cargar y compila, se genera una versión comprimida del paquete principal se creó. Abre la consola de Glitch para ver lo que contiene. directorio final public/ que entrega el servidor de Node.

  • Haz clic en el botón Herramientas.
  • Haz clic en el botón Consola.
  • En la consola, ejecuta los siguientes comandos para cambiar a public. y verás todos sus archivos:
cd public
ls

Archivos finales de salida en el directorio público

La versión comprimida del paquete, main.bundle.js.gz, ahora se guarda aquí como en la nube. CompressionPlugin también comprime index.html de forma predeterminada.

Lo siguiente que debes hacer es indicarle al servidor que envíe estos archivos archivos cuando se soliciten sus versiones originales de JS. Esto se puede hacer Definiendo una ruta nueva en server.js antes de que los archivos se entreguen con express.static

const express = require('express');
const app = express();

app.get('*.js', (req, res, next) => {
  req.url = req.url + '.gz';
  res.set('Content-Encoding', 'gzip');
  next();
});

app.use(express.static('public'));

//...

app.get se usa para indicar al servidor cómo responder a una solicitud GET de un extremo específico. Luego, se usa una función de devolución de llamada para definir cómo controlar esto. para cada solicitud. La ruta funciona de la siguiente manera:

  • Especificar '*.js' como primer argumento significa que funciona para cada que se activa para recuperar un archivo JS.
  • En la devolución de llamada, se adjunta .gz a la URL de la solicitud y al El encabezado de respuesta de Content-Encoding se estableció en gzip.
  • Por último, next() garantiza que la secuencia continúe con cualquier devolución de llamada. que podrían usarse a continuación.

Una vez que se vuelva a cargar la app, vuelve a observar el panel Network.

Reducción del tamaño del paquete con compresión estática

Igual que antes, se redujo de forma significativa el tamaño del paquete.

Conclusión

En este codelab, se abarcó el proceso de reducir y comprimir el código fuente. Ambas técnicas se están convirtiendo en una opción predeterminada en muchas de las herramientas. por lo que es importante averiguar si tu cadena de herramientas ya los respalda o si debes comenzar a aplicar ambos procesos por tu cuenta.