- Últimamente, Node.js ha evolucionado rápidamente al integrar en el runtime funciones que antes solo eran posibles con paquetes npm
- Esto permite reducir los riesgos de seguridad en la cadena de suministro, mejorar la portabilidad del código, disminuir las dependencias y simplificar el mantenimiento, además de contribuir a asegurar rendimiento y estabilidad en entornos de producción
- Se han agregado APIs globales como
fetch(), WebSocket, node:test, por lo que ahora es posible desarrollar sin paquetes populares como node-fetch, ws o mocha
- Con la expansión de las funciones del sistema de archivos, se ofrecen opciones en
fs.glob(), fs.rm() y fs.mkdir() que reemplazan a glob, rimraf y mkdirp
- En las APIs de utilidades y criptografía,
crypto.randomUUID(), util.styleText() y atob/btoa ya vienen incluidos como estándar, haciendo innecesarios paquetes como uuid o chalk
- Algunas funciones (
node:sqlite, URLPattern, --env-file, ejecución de TypeScript, etc.) todavía permanecen en fase experimental
- Lo importante es que, gracias a la evolución interna de Node.js, ya es posible desarrollar aplicaciones modernas solo con el runtime base
Principales paquetes npm reemplazados por funciones nativas de Node.js
- Durante mucho tiempo, Node.js ha dependido de diversos paquetes npm como utilidades HTTP y helpers del sistema de archivos
- Sin embargo, en las versiones recientes (v18~v22), se ha fortalecido la tendencia de integrar estas funciones directamente en el runtime
- Como resultado, se reduce la complejidad de la gestión de paquetes y el riesgo de exposición en seguridad
1. node-fetch → Global fetch()
- Desde Node.js 18,
fetch() igual que en el navegador está disponible como función global
- Es posible manejar solicitudes HTTP sin
node-fetch
- Se introdujo de forma experimental en v17.5.0 y se estabilizó en v18.0.0
- Aun así, en versiones anteriores a la 18, sigue siendo necesario
node-fetch
2. ws → Global WebSocket
- Desde Node.js 21, la clase global
WebSocket permite conexiones WebSocket del lado del cliente
- Se agregó de forma experimental en v21.0.0 y hasta ahora sigue en fase experimental
- Para una implementación WebSocket del lado del servidor, todavía es necesario usar el paquete
ws u otras bibliotecas relacionadas
3. Frameworks de testing → node:test
- Desde Node.js 18, se ofrece el runner de pruebas nativo
node:test, que puede reemplazar a mocha, jest y otros
- Se introdujo experimentalmente en v18.0.0 y se estabilizó en v20.0.0
- Soporta la escritura y ejecución de pruebas unitarias básicas
- Si se necesitan snapshots, mocking y un ecosistema rico de plugins, los frameworks de terceros siguen siendo útiles
- Es suficiente para pruebas a nivel de módulo, pero en aplicaciones full stack los frameworks existentes todavía tienen ventajas
4. sqlite3 / better-sqlite3 → node:sqlite
- Node.js está incorporando el módulo experimental
node:sqlite para acceder a SQLite
- Resuelve problemas de compilación y errores al actualizar que eran comunes en paquetes con bindings nativos
- Soporta tareas básicas como crear bases de datos en memoria y crear tablas
- Como todavía está en fase experimental, si se necesitan ajustes avanzados de rendimiento o funciones adicionales, se recomienda usar paquetes de la comunidad
5. chalk / kleur → util.styleText()
- Desde Node.js 20.12.0,
util.styleText() permite dar estilo al texto en consola
- Se estabilizó en v22.17.0
- Aplica estilos básicos de texto como color, negrita y subrayado
- Si se necesitan temas complejos, sintaxis encadenable o compatibilidad hacia atrás, todavía se puede seguir usando
chalk y similares
6. strip-ansi → util.stripVTControlCharacters()
- Node.js ofrece de forma nativa una función para eliminar códigos de escape ANSI
- Permite eliminar caracteres de control de forma segura en logs
- La mayoría de los casos de uso quedan cubiertos de forma nativa, por lo que no hace falta un paquete de terceros
7. glob → fs.glob()
- Desde Node.js 22, se agregó la función nativa
fs.glob() para buscar archivos por patrón
- Se añadió en v22.0.0 y se estabilizó en v22.17.0 LTS
- Permite buscar archivos con patrones glob como
**/*.js
- Si se necesita compatibilidad con versiones antiguas de Node.js, conviene usar el paquete
glob
8. rimraf → fs.rm({ recursive: true })
- La eliminación recursiva de directorios está soportada por la API nativa de Node.js
- Se implementa con las opciones
recursive y force de fs.rm()
- Está disponible desde alrededor de v12.10.0 y hoy está estabilizada en todas las versiones LTS
- Es posible borrar directorios de forma segura sin el paquete
rimraf
9. mkdirp → fs.mkdir({ recursive: true })
- La creación recursiva de directorios se ofrece mediante la opción
recursive de fs.mkdir()
- Se agregó desde v10.12.0 y lleva mucho tiempo estabilizada
- Es posible crear directorios anidados sin paquetes adicionales
10. uuid → crypto.randomUUID()
- Desde Node.js 14.17.0, se ofrece la función de generación de UUID
crypto.randomUUID()
- Está incluida como una función estable del módulo de criptografía
- Es posible generar IDs aleatorios seguros sin el paquete
uuid
11. base64-js / atob → atob, btoa
- Desde Node.js 20, se ofrecen las funciones globales
atob y btoa
- Es la misma API de codificación/decodificación Base64 que en el navegador
- Ofrece una opción adicional además del uso tradicional de
Buffer
- Es posible procesar Base64 sin polyfills
12. url-pattern → URLPattern
- Desde Node.js 20, se ofrece experimentalmente la API global
URLPattern
- Soporta route matching y extracción de parámetros de ruta
- Aún está en fase experimental y necesita estabilizarse
- Es posible manejar patrones de URL con una Web API estándar
13. dotenv → flag --env-file
- Desde Node.js 20.10.0, se soporta la carga de variables de entorno con el flag
--env-file
- Carga directamente el archivo
.env al ejecutar
- Todavía está en fase experimental
- Para funciones avanzadas como expansión de variables o múltiples archivos env, sigue siendo necesario el paquete
dotenv
14. event-target-shim → EventTarget
- Desde Node.js 15.0.0, se ofrece globalmente el sistema de eventos estándar de la Web
EventTarget
- Se estabilizó en v15.4.0
- Soporta el mismo modelo de manejo de eventos que en el navegador
- Puede usarse como alternativa a
EventEmitter
15. tsc → ejecución de TypeScript en Node.js
- Desde Node.js 21, es posible ejecutar archivos
.ts directamente con el flag --experimental-strip-types
- Solo elimina tipos; no soporta type checking completo
- Todavía está en fase experimental
- Para builds de producción, verificación estática de tipos, generación de archivos de declaración y type checking completo,
tsc sigue siendo necesario
Conclusión
- La dirección en la que evoluciona Node.js es reducir la dependencia de paquetes externos y elevar el nivel de completitud de la propia plataforma
- En la versión LTS más reciente (v22), muchos paquetes npm ya se han vuelto innecesarios,
lo que representa una gran mejora en seguridad, rendimiento y mantenibilidad
- En entornos empresariales, se están usando soluciones como N|Solid para monitorear estos cambios en tiempo real
- Análisis del rendimiento en cargas reales de funciones nativas como
fetch, node:test, crypto.randomUUID(), etc.
- El agente de IA N|Sentinel proporciona monitoreo de uso y recomendaciones de optimización a nivel de código
6 comentarios
Las API que ofrece el runtime siguen aumentando cada vez más..
Sobre todo cosas como la API de red, URL, b64 y otras API de procesamiento de cadenas, etc...
Esto ya es totalmente... PH..
Parece que UUID v7 todavía es demasiado pronto.
Creo que un driver de base de datos debería verse desde una perspectiva distinta a la de otras funciones que deberían entrar en la librería estándar; tanto en Bun como aquí, ¿cuál es la razón para intentar incorporar un driver de SQLite en el runtime?
¿Será porque Python lo trae integrado?
Más que integrar la funcionalidad de SQLite, creo que es más importante crear un estándar de interfaz para drivers de base de datos.
Como la interfaz cambia según el driver, ¿no es ese precisamente el problema, que para dar soporte a bases de datos heterogéneas es difícil hacerlo sin usar un ORM?
Supongo que lo incluyeron porque para servicios pequeños, como un blog personal, muchas veces con sqlite es más que suficiente. Si está, resulta práctico.
Creo que incluyeron
sqliteporque tiene la interfaz más simple y sirve como una buena referencia para consultar.Y no entiendo por qué habría que crear un estándar para la interfaz de los drivers de DB. Me suena haber visto algo parecido en PHP.
Para las consultas complejas que un ORM no puede manejar, todavía se siguen usando consultas RAW...
Parece que usas varios tipos de bases de datos con frecuencia... ¿Qué tal si creas una librería? :)
Es bastante común que runtimes como Python, Java, C#, Go, etc. creen una interfaz estándar para los drivers de base de datos.
Pero en Node, incluso entre drivers que apuntan al mismo SQLite, la ejecución de sentencias cambia entre
execute()yexec(), así que hasta reemplazar solo el driver requiere hacer cierto nivel de modificaciones.No es algo que pase muy seguido, pero cuando cambias de base de datos también resulta incómodo.
Por ejemplo, si usabas MySQL pero no te convence algo de lo que hace Oracle, o si necesitas alguna extensión indispensable de PostgreSQL y decides migrar a PostgreSQL, en los casos donde existe una interfaz estándar como JDBC basta con validar el SQL, pero en el ecosistema de Node está el efecto secundario de tener que rehacer toda la lógica de llamadas a la base de datos.
+Me recomendaron crear una librería, pero para crear una librería también es mucho más cómodo cuando existe un estándar de interfaz común.
En la empresa usamos Java, y como en nuestro framework interno tenemos que soportar MySQL, DB2, Oracle y MSSQL, al dar mantenimiento a los adaptadores de cada base de datos nos hemos beneficiado mucho del estándar JDBC.