Learn Node.js construyendo un marco de backend - Velocy

Puede acceder a la versión actual del libro en el directorio de capítulos o en formato PDF (tanto los modos de luz como oscuro están disponibles) haciendo clic aquí. Tenga en cuenta que esta versión incluye la versión actual del contenido, y no es la versión final.
Este libro todavía está en una etapa muy temprana. Contiene una porción insignificante del contenido total que se supone que debe cubrir el libro. Habrá 0 dependencias para nuestro marco de backend, así como para nuestra biblioteca de registro. Todo se hará usando Vanilla Node.js, el camino duro (la mejor manera de aprender).
Nota
Si no está familiarizado con JavaScript, también puede consultar mi otro repositorio, Learn JavaScript, la forma fácil que lo lleva a un viaje profundo y divertido a JavaScript, desde los conceptos básicos hasta los conceptos avanzados que nunca necesitaría, sin sumergirse en demasiada teoría. Solo ejemplos prácticos de código.
Para dominar un nuevo concepto, a menudo es mejor comenzar desde cero. Esta no es solo otra guía de nodo.js; Es una experiencia integral de código y el objetivo destinado a construir un producto del mundo real que puede ser utilizado por miles de desarrolladores. El producto que vamos a construir será un marco de backend, que también desde cero.
No solo aprenderá cómo funciona Node.js, sino también por qué funciona de una manera particular. La guía también incluye discusiones sobre estructuras de datos relevantes y patrones de diseño.
El libro también incluye una amplia gama de ejercicios creados específicamente para desafiarlo, que pueden requerir compromiso y esfuerzo constante de su parte. Los primeros ejercicios comienzan desde el capítulo 7
Esta guía va más allá de lo básico. Estamos enfocados en ofrecer un marco de backend modular y optimizado que esté cerca de estar listo para estar listo. Se cubrirán temas como la optimización del rendimiento, las medidas de seguridad y varios enfoques de prueba para garantizar que el marco sea confiable y extensible.
Recomiendo encarecidamente codificar activamente junto con esta guía, en lugar de solo leerla, para una comprensión completa de Node.js y sus aspectos más intrincados.
El repositorio para nuestra velocidad del marco de backend. (WIP)

Tabla de contenido
- (Opcional) node.js es mucho más rápido de lo que piensas
- Contendientes para la prueba
- Elysia - Bun
- Axum - óxido
- Express - node.js
- Velocidad - node.js
- El punto de referencia
- Código fuente
- Elysia - Bun
- Axum - óxido
- Express - node.js
- Velocidad - node.js
- Resultados: punto de referencia típico
- Resultado: Elysia - Bun/Zig (149,047 req/s)
- Resultado: Axum - Rust (208,938 req/s)
- Resultado: express - node.js (28,923 req/s)
- Resultado: Velocy - Node.js (83,689)
- Gráficos
- Estado latente
- Solicitudes/seg
- Memoria inactiva
- Memoria bajo carga constante
- Veredicto - punto de referencia típico
- El verdadero punto de referencia
- Actualización de nuestro código
- Elysia
- Expresar
- Velocidad
- Resultados: un caso de uso del mundo real
- Resultado: expreso - nodo (50,275 req/seg)
- Resultado: Velocy - Nodo (138,956 REQ/SEC)
- Estado latente
- Latencia sin barra
max latency - Solicitudes/seg
- Memoria inactiva
- Memoria bajo carga constante
- Veredicto final
- ¿Qué diablos es un servidor web de alguna manera?
- Partes de un servidor web:
- Navegar por el mundo de los protocolos: una visión general rápida
- La relación entre HTTP y TCP: garantizar una comunicación web confiable
- 1. Integridad y orden de datos
- 2. Mecanismo de reconocimiento
- 3. Interacciones complejas
- 4. Overhead de transmisión
- Preguntar y obtener: cómo responden los servidores web a sus solicitudes
- La solicitud:
- La respuesta:
- Su primer programa
node.js- ¿Qué es exactamente Node o NodeJS?
- Su primer programa Node.js
- ¿Cómo funciona
console.log() en node.js? - El objeto
process : - La propiedad
stdout del objeto process :
- Trabajando con archivos
- ¿Qué hará la biblioteca de registro?
- ¿Cómo trabajas con los archivos de todos modos?
- Volvamos a
files - Un poco más sobre los descriptores de archivos
- Creando nuestro primer archivo
- argumento
path - argumento
flag - argumento
mode - Lectura de un archivo
- Una pequeña imprimación
for..of y for await..of ... de JavaScript - Leyendo el archivo
json - Buffers
-
logtar nuestra propia biblioteca de registro- Inicializando un nuevo proyecto
- Un poco sobre
SemVer - Creando una clase
LogLevel - La clase
Logger- Encapsulación con campos
private
- La clase
LogConfig - Patrones de diseño
- Uso del patrón
builder con la clase LogConfig - Comentarios de JSDOC
- La clase
RollingConfig- La clase
RollingSizeOptions - La clase de
RollingTimeOptions
- Terminando la clase
RollingConfig - Agregar métodos más útiles en la clase
LogConfig - Refactorizar el código
- La necesidad de refactorizar
- Creación de archivos separados
- El archivo
index.js - El archivo
lib/logtar.js - El archivo
lib/logger.js - El archivo
lib/config/log-config.js - El archivo
lib/config/rolling-config.js - El archivo
lib/utils/log-level.js - La clase
lib/utils/rolling-options.js
- Registros de escritura
- 1. Reutilización del mango del archivo
- 2. Rotación de registro
- 3. Registro asíncrono
- 4. Obtener información de la persona que llama (módulo y número de línea)
- Probar nuestra API actual
- Implementación de métodos de registro
- Secar (no se repita)
- El método
log - Considerando la variable de miembro
log_level - Escribir en un archivo
- Otro Gotcha
- Configuración del directorio de registros
- El objeto
require - Agregar un nuevo ayudante para crear directorio de registro
- Actualización del método
init - Completar el método
log
- Capturando metadatos
- ¿Qué es una pila?
- Ejemplos de pilas
- La pila de llamadas
- Obtener la información de la pila
- Obtener el nombre de
callee y el número de línea - Una forma más ergonómica
- Usando la función
get_caller_info
- Una pequeña introducción a
async vs sync- El equilibrio entre los opuestos
- Mezcla de código asincrónico y sincrónico
- E/S más rápido fuera de la caja
- Código de bloqueo
- Concurrencia
- Agregar soporte de archivo rodante
- Características rodantes
- El método
rolling_check() -
file_handle.stat() - Llamar al método
rolling_check - ¡Una gran gotcha!
- Stack traza a través de puntos
await- Probar la nueva creación de archivos de registro
- Http buceo profundo
- Un pequeño servidor web
- Iniciar nuestro servidor web
- Probar nuestro servidor web
- Prueba con
cURL
- Verbos HTTP, versiones y los beneficios de
HTTP/1.1-
GET - Recuperar datos -
POST - Crea algo -
PUT - reemplazar o crear -
HEAD - Recuperar metadatos -
DELETE : eliminar de la existencia -
PATCH - Actualizaciones parciales - Un pequeño resumen
- El
/ camino -
HTTP/0.9 -
HTTP/1.0 -
HTTP/1.1
- Agentes de usuarios
-
User-Agent puede ser raro
- Tipo mime y
Content-Type- Comprender el encabezado
Accept - Tipo mimo
- Anatomía de un tipo mime
- ¿Pero por qué el comodín
*/* ? - El encabezado
Content-Type - El
charset=UTF-8 : codificación de caracteres
- Encabezado
- Nombre de encabezado
- Colon (
: - Valor de encabezado
- Whitepace
- Encabezados personalizados basados en
X-
- Solicitar encabezados
- Aceptar
- Referente
- Autorización
- Galleta
- Anfitrión
- Tipo de contenido (solicitud)
- Encabezados de respuesta
- Tipo de contenido (respuesta)
- Control de caché
- Cocinero
- Códigos de respuesta y estado
-
Connection: close en acción - Códigos de estado
-
Velocy - Nuestro marco de backend- ¿Por qué la velocidad?
- ¿Qué es un marco de backend/biblioteca de todos modos?
- Características centrales de nuestro marco de backend
- Enrutamiento y manejo de URL:
- Middlewares
- Construyendo nuestra propia base de datos
- Almacenamiento en caché
- Limitación de tasas
- Algunas otras características que implementaremos
- Una implementación básica
Router- Un enrutador de juguete
-
Transfer-Encoding: chunked - Trozos, oh no!
- Especificando
Content-Length - Reutilización del código
- La clase
Router- Uso de
Router con un servidor HTTP
-
this no es bueno- Contexto léxico
- Las funciones de flecha no son gratuitas
- ¿Por qué deberíamos preocuparnos por la memoria?
- Probar el código actualizado
- Mejora de la API
Router - La necesidad de un
Trie- ¿Qué es un
Trie de todos modos?
- Ex. Implementando un
Trie- Nodo raíz
- Fin de la palabra
- Desafío 1: TRie básico con método
insert - Desafío 2: Implementar el método
search
- Ex. Implementación de nuestro
Router basado en Trie- Desafío 1: Implementación del método
addRoute - Desafío 2: Implementación del método
findRoute
- Ex. Agregar soporte del método
HTTP- Requisitos
- Más detalles
- Ejemplo
- Pistas
- Solución
- Agregar métodos HTTP al enrutador
- Actualizar la clase
TrieRouter
- Ex. Implementación de enrutamiento dinámico
- ¿Por qué enrutamiento dinámico?
- Anatomía de una ruta dinámica
- Desafío: Mejore la clase
TrieRouter para admitir el enrutamiento dinámico - Visualización de nuestra estructura
TrieRouter - Resumen
- Ejecutando nuestro servidor
- Refactorizar la clase
TrieRouter - Tipo alias
- La función
run
- Construyendo nuestro primer servidor web
- Más refactorización
- Su primer servidor web
- Ex. Parámetros de consulta (avanzado)
- Anatomía de una URL con parámetros de consulta
- Desafío 1: Implementación de la analización de parámetros de consulta básica
- Necesitamos abordar más casos de borde
- Desafío 2: Parámetros de consulta de análisis manualmente