Optimice su aplicación con HTTP/2 Server Push usando Node y Express

HTTP/2 es el nuevo estándar de la web. Tiene muchas características excelentes que harán que la web sea más rápida y simplificará el desarrollo. Por ejemplo, no es necesario concatenar archivos gracias a la multiplexación o a un servidor que puede enviar archivos antes de que un navegador sepa que los necesita.

Esta publicación no cubrirá todas las ventajas de HTTP/2. Puedes leer sobre ellos en línea. No es necesario entrar en todos los detalles y duplicar el texto aquí. En su lugar, nos centraremos en la inserción del servidor y la implementaremos en Node.js usando Express y el spdy biblioteca.

Empuje del servidor:¡sí!

La forma en que funciona la inserción del servidor es agrupando múltiples activos y recursos en una sola llamada HTTP/2. Bajo el capó, el servidor emitirá un PUSH_PROMISE. Los clientes (navegadores incluidos) pueden usarlo o no dependiendo de si el archivo HTML principal lo necesita. Si es así, lo necesita, entonces el cliente coincidirá con las promesas de inserción recibidas para que se vean como llamadas GET HTTP/2 normales. Obviamente, si hay una coincidencia, no se realizarán nuevas llamadas, pero se utilizarán los activos que ya están en el cliente. Algunos buenos artículos para obtener más información sobre los beneficios de inserción del servidor.

  • ¿Cuál es el beneficio de Server Push?
  • Anuncio de la compatibilidad con HTTP/2 Server Push
  • Innovando con HTTP 2.0 Server Push

Este es un artículo práctico que se centra en la implementación del servidor HTTP/2 en Node. Para ser más precisos, implementaremos un servidor Node y Express con una sola ruta /pushy que empuja un archivo JavaScript. Como se mencionó anteriormente, usaremos el spdy biblioteca.

HTTP/2 y Node.js

Unas palabras sobre la elección del spdy biblioteca para Node:a partir de ahora, hay dos implementaciones principales de HTTP/2 para Node.js:

  • http2
  • spdy

Ambos son muy similares al núcleo http y https módulos, lo que significa que si no usa Express, hay muy poca diferencia. Sin embargo, el spdy biblioteca admite HTTP/2 y Express, mientras que http2 La biblioteca no es compatible con Express en este momento. Esta es una razón sólida para usar spdy porque seamos sinceros, Express es el marco estándar de facto para las aplicaciones web de Node. Por eso elegí spdy . El nombre spdy es del protocolo Google SPDY que se convirtió en HTTP/2.

Certificados y claves HTTPS

En primer lugar, deberá generar una clave y un certificado para poder usar el cifrado HTTPS, porque esa es la única forma en que HTTP/2 funcionará en sus navegadores (Firefox, Safari, Chrome o Edge). Continúe y busque "generación de clave ssl" o siga los pasos a continuación (porque no enviaré mi clave y certificado al repositorio de GitHub para este proyecto):

$ mkdir http2-node-server-push 
$ cd http2-node-server-push
$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048

Luego ejecuta esto:

$ openssl rsa -passin pass:x -in server.pass.key -out server.key

Observa:

writing RSA key

Deshágase de RSA:

$ rm server.pass.key
$ openssl req -new -key server.key -out server.csr

Responder preguntas:

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
A challenge password []:
...

Finalmente ejecuta:

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

Al final, deberías tener tres archivos SSL:

  • server.crt
  • server.csr
  • server.key

Estarás leyendo desde server.key y server.crt en su script de servidor Node.js.

[Nota al margen]

Leer publicaciones de blog es bueno, pero ver cursos en video es aún mejor porque son más atractivos.

Muchos desarrolladores se quejaron de la falta de material de video de calidad asequible en Node. Es una distracción ver videos de YouTube y una locura pagar $ 500 por un curso de video de Node.

Visite Node University, que tiene cursos de video GRATUITOS en Node:node.university.

[Fin de la nota al margen]

Estructura del proyecto

Ahora es un buen momento para crear un package.json archivo e instalación de dependencias:

npm init -y
npm i [email protected] [email protected] [email protected] --save
npm i [email protected] --save-dev

y la carpeta del proyecto se verá:

 /http2-node-server-push
   /node_modules
  - index.js
  - package.json
  - server.crt
  - server.csr
  - server.key

Siéntase libre de agregar estos dos scripts npm en scripts de package.json para simplificar los comandos de lanzamiento (que usan node-dev para la recarga automática):

    "start": "./node_modules/.bin/node-dev .",
    "start-advanced": "./node_modules/.bin/node-dev index-advanced.js"

Ahora estamos listos para implementar una inserción de servidor simple usando Node, Express y spdy.

Implementación de un servidor Push HTTP/2 con Node.js y Express.js

En primer lugar, importe las dependencias. Crear index.js en la misma carpeta que package.json (ver estructura del proyecto arriba).

Estoy usando la nueva y elegante sintaxis ES6/ES2015 de const para declarar mis módulos. Si no está familiarizado con este tipo de declaraciones, consulte
Las 10 funciones principales de ES6 que todo desarrollador de JavaScript ocupado debe conocer .

const http2 = require('spdy')
const logger = require('morgan')
const express = require('express')
const app = express()
const fs = require('fs')

A continuación, aplicaremos el registrador de morgan para ver qué solicitudes recibe el servidor:

app.use(logger('dev'))

Ahora, hay una página de inicio en la que le decimos que vaya a /pushy que será nuestra página de inserción del servidor.

app.get('/', function (req, res) {
  res.send(`hello, http2!
go to /pushy`)
})

El impulso del servidor se implementa fácilmente usando res.push que viene de spdy. Pasamos el nombre del archivo que usará el navegador para hacer coincidir la promesa de inserción con el activo. Por lo tanto, el /main.js en res.push() debe coincidir con lo que solicitará en HTML.

El segundo argumento es un objeto. Es opcional y establece la información de activos enviados:

app.get('/pushy', (req, res) => {
  var stream = res.push('/main.js', {
    status: 200, // optional
    method: 'GET', // optional
    request: {
      accept: '*/*'
    },
    response: {
      'content-type': 'application/javascript'
    }
  })
  stream.on('error', function() {
  })
  stream.end('alert("hello from push stream!");')
  res.end('<script src="/main.js"></script>')
})

Como puedes observar, stream tiene métodos on y end . El primero permitirá escuchar eventos con como error o finish . Esto último es cuando hemos terminado. El main.js script mostrará un cuadro de alerta (webdev alrededor de 1990).

Alternativamente, puede usar res.write() y luego res.end() al final, si tiene varios fragmentos de datos, porque end() cerrará automáticamente la respuesta mientras write déjala abierta. (Este enfoque no se muestra en la implementación actual).

Por último, activemos el servidor cargando primero los datos SSL, como la clave y el certificado, y luego usando spdy (el http2 var) para arrancar el servidor.

var options = {
  key: fs.readFileSync('./server.key'),
  cert: fs.readFileSync('./server.crt')
}

http2
  .createServer(options, app)
  .listen(8080, ()=>{
    console.log(`Server is listening on https://localhost:8080.
You can open the URL in the browser.`)
  }
)

La esencia de esta implementación:se trata de flujos. No el que puede encontrar en el bosque, sino el que los desarrolladores usan una vez para canalizar los datos desde el origen hasta el destino. Si no sabe nada sobre la transmisión o si la solicitud y la respuesta http en Node y Express son transmisión, consulte No conoce el nodo .

Ejecutar y diferenciar HTTP/2 Server Push

Ejecuta esto con node index.js o npm stat . Vaya a https://localhost:3000/pushy y vea el cuadro de alerta. ¡Auge! Ni siquiera teníamos un archivo para eso, y si revisa los registros de terminal del servidor:

GET /pushy 200 4.918 ms - -

Esa es solo una solicitud, no dos (una para HTML y otra para JS como sería el caso sin la inserción del servidor).

Examinemos el comportamiento del navegador cuando se trata de la inserción del servidor. Abra DevTools en Chrome (o una herramienta similar si no está usando Chrome) y vaya a la pestaña Red. Verás que nuestro main.js NO tiene una barra de saludo, lo que significa que no hay tiempo de espera de TTFB (explicación).


Además, ¿ve que la solicitud se inicia (columna Iniciador) mediante Push? En HTTP/2 o HTTP/1 sin inserción de servidor, habría un nombre de archivo, por ejemplo, index.html .

Misión cumplida. Usamos Express y spdy para enviar fácilmente el activo de JavaScript que luego fue utilizado por el servidor porque en el HTML teníamos <script> .

Nada le impide tener activos como archivos y en sus scripts de Node leerlos con fs . De hecho, esa es mi implementación del middleware push del servidor de activos estáticos HTTP/2 para Express, que cubriré en la próxima publicación (puede echarle un vistazo aquí).

Resumen

HTTP/2 tiene muchas características excelentes y la inserción del servidor podría ser una de las características más buscadas de todas. El beneficio de los servidores push es que cuando un navegador solicita una página, el servidor envía los activos necesarios (imágenes, hojas de estilo, scripts) de inmediato sin tener que esperar a que el cliente los solicite (lo que puede retrasarse con el renderizado).

spdy proporciona a los desarrolladores de Node una manera fácil de habilitar las inserciones en sus aplicaciones Express. Usted clona el código fuente de este artículo para reproducirlo o usarlo como su plantilla (GitHub) para crear una inserción en el servidor de sus activos.