Servidor HTTP/2 sencillo con Node.js y Express.js

La Internet moderna con su protocolo TCP/IP comenzó alrededor de 1975, lo cual es sorprendente hace 41 años. Durante la mayor parte de su existencia, usamos HTTP y su sucesor HTTP/1.1 (versión 1.1) para comunicarnos entre clientes y servidores. Sirvió bien a la web, pero la forma en que los desarrolladores construyen sitios web ha cambiado drásticamente. Hay miles de recursos externos, imágenes, archivos CSS, activos de JavaScript. El número de recursos solo está aumentando.

¡HTTP2 es la primera actualización importante del antiguo protocolo HTTP en más de 15 años (el primer HTTP es alrededor de 1991)! Está optimizado para sitios web modernos. El rendimiento es mejor sin trucos complicados como fragmentación de dominios (tener varios dominios) o concatenación de archivos (tener un archivo grande en lugar de muchos pequeños).

H2 es el nuevo estándar para la web que comenzó como el protocolo SPDY de Google. Ya lo utilizan muchos sitios web populares y es compatible con la mayoría de los principales navegadores. Por ejemplo, fui a Flickr de Yahoo y ya está usando el protocolo h2 (HTTP2) (a partir de julio de 2016).

Flickr de Yahoo ya está usando el protocolo h2 (HTTP2)

HTTP/2 semánticamente no es diferente de HTTP/1.1, lo que significa que tiene el mismo lenguaje similar a XML en el cuerpo y también los mismos campos de encabezado, códigos de estado, cookies, métodos, URL, etc. H2. Los beneficios de H2 incluyen:

  1. Multiplexación:permite que los navegadores incluyan varias solicitudes en una única conexión TCP que, a su vez, permite a los navegadores solicitar todos los activos en paralelo.
  2. Server push:los servidores pueden enviar recursos web (CSS, JS, imágenes) antes de que un navegador sepa que los necesita, lo que acelera los tiempos de carga de la página al reducir el número de solicitudes.
  3. Prioridad de transmisión:permite a los navegadores especificar la prioridad de los activos. Por ejemplo, el navegador puede solicitar HTML primero para representarlo antes que cualquier estilo o JavaScript.
  4. Compresión de encabezado:todas las solicitudes HTTP/1.1 deben tener encabezados que normalmente duplican la misma información, mientras que H2 obliga a que todos los encabezados HTTP se envíen en un formato comprimido.
  5. Cifrado obligatorio de facto:aunque el cifrado no es obligatorio, la mayoría de los principales navegadores implementan H2 solo sobre TLS (HTTPS).

Si bien hay algunas críticas a H2, es claramente un camino a seguir por ahora (hasta que tengamos algo aún mejor). Por lo tanto, veamos qué necesita saber como desarrollador web. Bueno, la mayoría de los trucos de optimización que conoce se vuelven innecesarios, y algunos de ellos incluso afectarán el rendimiento del sitio web. Estoy hablando de la concatenación de archivos. Deje de hacer eso (sprites de imagen, CSS y JS incluidos), porque cada pequeño cambio en su archivo grande invalidará el caché. Es mejor tener muchos archivos pequeños. Espero que la necesidad de herramientas de compilación como Grunt, Gulp y Webpack disminuya debido a eso. Introducen complejidad adicional, una curva de aprendizaje pronunciada y dependencias a los proyectos web.

Otra cosa que hicieron los buenos desarrolladores en el mundo HTTP/1.1, y que te perjudicará en H2 es el sharding (truco para superar el límite de conexión TCP activo en los navegadores). De acuerdo, puede que no duela en todos los casos, pero no hay beneficios desde ahora de la multiplexación. No fragmente el dominio en HTTP2 porque cada dominio incurre en una sobrecarga adicional. Si es necesario, resuelva los dominios en la misma IP y asegúrese de que sus certificados tengan un comodín que los haga válidos para los subdominios o que tengan un certificado multidominio.

Para obtener más información sobre HTTP/2, consulte el sitio web oficial. Ahora aprenderemos cómo podemos crear un servidor HTTP/2 con Node.js En primer lugar, cree una carpeta vacía y un certificado SSL autofirmado en ella:

$ mkdir http2-express 
$ cd http2-express
$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
...
$ openssl rsa -passin pass:x -in server.pass.key -out server.key
writing RSA key
$ rm server.pass.key
$ openssl req -new -key server.key -out server.csr
...
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
...
A challenge password []:
...
$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

Cuando visite su servidor, asegúrese de seleccionar "AVANZADO" y "Proceder a localhost (inseguro)" o agregue localhost como una excepción. El motivo es que los navegadores no confían en los certificados autofirmados de forma predeterminada.

Haga clic en AVANZADO

Pero es su certificado, así que está bien continuar.

Haga clic en Proceder a localhost (inseguro)

Luego, necesitamos inicializar package.json y descarga spdy y express :

npm init
npm i express spdy --save

Ahora puedes crear index.js que será un punto de entrada de nuestra aplicación. Comienza con algunas importaciones e instancias:

const port = 3000
const spdy = require('spdy')
const express = require('express')
const path = require('path')
const fs = require('fs')

const app = express()

A continuación, definimos una ruta Express:

app.get('*', (req, res) => {
    res
      .status(200)
      .json({message: 'ok'})
})

Luego, necesitamos cargar los archivos de clave y certificado. Este es probablemente uno de los pocos casos en los que podemos usar fs.readFileSync() :

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

Por último, cargamos las opciones SSL en nuestro servidor junto con la instancia Express:

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

spdy
  .createServer(options, app)
  .listen(port, (error) => {
    if (error) {
      console.error(error)
      return process.exit(1)
    } else {
      console.log('Listening on port: ' + port + '.')
    }
  })

Cuando inicias el servidor con node . , puede realizar solicitudes CURL (asegúrese de tener la última versión 7.46 con nghttp2 ) con curl https://localhost:3000/ -k para ver la respuesta (-k es hacer que CURL esté de acuerdo con el certificado autofirmado).

Usando CURL con h2

Otra forma de verificar que tenemos H2 es usar DevTools como hicimos con Flickr al comienzo de esta publicación.

Inspección de H2 en DevTools

Eso es todo. Como puede observar, construir un servidor HTTP2 con Node.js y Express.js es sencillo. En la mayoría de los casos, no necesitará hacer muchos cambios. Lo más probable es que ya esté usando HTTPS/SSL (y si no lo está, DEBERÍA hacerlo, a menos que su servidor sea solo para activos estáticos). Entonces, tendrías que cambiar tu https para spdy .

También hay otra biblioteca para H2 llamada http2 , pero no funciona con la última versión de Express. Puedes usar http2 sin Express o simplemente espera a Express v5.

Al final, HTTP/2 ofrece más beneficios y elimina la complejidad de algunos trucos de optimización web. Comience a cosechar la recompensa de H2 ahora implementándolo en sus servidores. ¡Adelante hacia un futuro brillante!

PD:El código fuente del servidor HTTP/2 Express.js en funcionamiento se encuentra en el repositorio github.com/azat-co/http2-express.