Deno y Node.js tienen mucho en común. Ambos son entornos de ejecución de JavaScript fuera del navegador construidos sobre el motor V8. Sin embargo, Deno y Node.js también son diferentes en muchos aspectos: TypeScript, CommonJS, gestión de paquetes, sistemas de permisos, herramientas, complementos nativos, compatibilidad con navegadores. Esta charla comparará y contrastará los dos entornos de ejecución, centrándose en lo que los desarrolladores experimentados de Node.js necesitan saber para tener éxito con Deno.
Una Introducción a Deno para Desarrolladores de Node.js
Video Summary and Transcription
Esta charla proporciona una introducción a Deno para desarrolladores de Node.js, destacando las diferencias en arquitectura y dependencias entre los dos entornos de ejecución. Se discute la interfaz de línea de comandos (CLI) y la cadena de herramientas integrada de Deno, la biblioteca estándar de Deno y la gestión de dependencias, así como el entorno de ejecución de Deno y sus características principales. La charla también cubre el sistema de permisos de Deno, su enfoque en la compatibilidad con la plataforma web y su soporte para TypeScript. En general, proporciona una visión general completa de Deno y sus ventajas sobre Node.js.
1. Introducción a Deno para desarrolladores de Node.js
Voy a hablar sobre cómo empezar con Deno si eres un desarrollador de Node.js. He estado usando Node durante unos 10 años y recientemente comencé a trabajar en Deno. Node.js ha estado presente durante mucho más tiempo, desde alrededor de 2009, y luego Deno salió unos 10 años después. Lo interesante de Node.js es que es anterior a gran parte de lo que consideramos como JavaScript moderno. Deno ha adoptado un enfoque diferente, donde incluye muchas más funcionalidades. Tiene una cadena de herramientas integrada y muchas otras cosas. Node.js tiene un ecosistema enorme con mucho código heredado. Tener un ecosistema enorme es bueno, pero tener que mantener tanto código heredado puede ralentizar el progreso y dificultar la capacidad de Node de cumplir con los estándares.
Hola a todos. Gracias por venir a mi charla. Voy a hablar sobre cómo empezar con Deno si eres un desarrollador de Node.js. Un poco de antecedentes personales sobre mí, he estado usando Node durante unos 10 años y recientemente comencé a trabajar en Deno. Ha sido una experiencia de aprendizaje tratar de cambiar entre estos dos entornos. Espero que esta charla pueda ayudar a alguien más que esté en mi situación al hacer la transición a Deno. Un poco de antecedentes sobre ambos entornos de ejecución. Ambos son entornos de ejecución de JavaScript y están construidos sobre el motor V8. Node.js ha estado presente durante mucho más tiempo, desde alrededor de 2009, y luego Deno salió unos 10 años después. Lo interesante de Node.js es que es anterior a gran parte de lo que consideramos como JavaScript moderno. Por ejemplo, todavía admite CommonJS, aunque tiene módulos ES. Aún tiene sus antiguas API de devolución de llamada, aunque ahora tiene soporte para muchas API basadas en promesas. Históricamente, Node también ha adoptado un enfoque de delegar todo al usuario. La idea era que el núcleo fuera mínimo y que el usuario implementara módulos de NPM para muchas otras funcionalidades. Diría que Deno ha adoptado un enfoque diferente, donde incluye muchas más funcionalidades. Tiene una cadena de herramientas integrada y muchas otras cosas, de las cuales hablaré más adelante en estas diapositivas. Otra cosa es que Node.js tiene un ecosistema enorme con mucho código heredado. Esto puede ser bueno y malo, tener un ecosistema enorme es bueno. Pero tener que mantener tanto código heredado puede ralentizar el progreso y dificultar la capacidad de Node de cumplir con los estándares, de lo cual hablaré más adelante en las diapositivas.
2. Línea de tiempo de Deno, DenoDeploy y Crecimiento
La línea de tiempo de Deno, el lanzamiento de Deno 1.0.0, el anuncio de la empresa Deno y la introducción de DenoDeploy. DenoDeploy es una máquina virtual de JavaScript distribuida globalmente para implementación en la nube. El crecimiento de Deno en términos de estrellas en GitHub en comparación con Node.js. A continuación, se discutirán las tecnologías principales de los dos proyectos.
Entonces, la línea de tiempo de Deno se muestra aproximadamente aquí. En junio de 2018, Deno se presentó por primera vez en JS Conf EU. Más tarde ese mismo año, en agosto, se lanzó Deno 0.1.0 y se reescribió en Rust. Inicialmente, las partes nativas de Deno estaban escritas en Golang y luego se trasladaron a Rust debido a preocupaciones sobre tener múltiples recolectores de basura ejecutándose en el mismo proceso.
Luego, en mayo de 2020, finalmente se lanzó Deno 1.0.0. En marzo de 2021, se anunció la empresa Deno. Esto es bueno porque tener una empresa respaldando un proyecto realmente puede ayudar, ya que se puede establecer una hoja de ruta, asignar trabajadores para trabajar en cosas específicas y tener un mejor control sobre cómo se desarrollará el proyecto. Por otro lado, Node.js es administrado casi en su totalidad por voluntarios. En el lado de Node, no podemos controlar quién trabajará en qué. No podemos decirles a los voluntarios que dediquen su tiempo a ciertas características. Incluso hemos tenido iniciativas como el Grupo de Trabajo de Evaluación de Rendimiento de Node, que está haciendo un trabajo muy útil, pero tuvieron que ser cerradas porque en ese momento no había nadie trabajando en ellas. En mi opinión, tener una empresa respaldando el proyecto es enorme.
Luego, en junio de 2021, se anunció DenoDeploy. DenoDeploy es una máquina virtual muy similar al proyecto de código abierto Deno, excepto que está destinada a ser implementada en la nube. Es más o menos una máquina virtual de JavaScript distribuida globalmente que te permite ejecutar programas de JavaScript en el borde de todo el mundo. Actualmente, se admiten 32 ubicaciones de borde diferentes y constantemente estamos agregando más. Es bueno porque puedes escribir tu código y tenerlo implementado en menos de 10 segundos a nivel global. Y en el tercer trimestre de este año, nuestro objetivo es lograr que DenoDeploy esté disponible para el público en general. Actualmente, todavía está en una versión beta pública.
Quería hablar rápidamente sobre el crecimiento aquí. Este gráfico muestra las estrellas en GitHub para la CLI de Deno y Node.js. El gráfico solo se genera hasta alrededor de 2015, aunque Node se remonta a 2009. Por lo tanto, la flecha que se muestra allí debería ser más ancha. Las estrellas en GitHub son una métrica de proxy para la adopción. Cualquiera puede marcar con estrella un repositorio de GitHub sin necesariamente usar el proyecto. Pero tenemos algunas métricas internas que indican que este crecimiento es real y no solo algo superficial en GitHub. Creo que, en base a la diferencia de 10 años en la edad de los dos proyectos, la diferencia en las estrellas es algo que vale la pena destacar. A continuación, quiero hablar sobre las tecnologías principales que se encuentran en los dos proyectos.
3. Arquitectura de Deno y Node.js
Tanto Deno como Node.js son entornos de ejecución de JavaScript construidos sobre V8. Sin embargo, Deno está escrito en Rust, lo que ofrece seguridad de memoria y otras ventajas sobre C++. Esta elección de lenguaje influye en las dependencias del proyecto.
Como mencioné anteriormente, ambos proyectos son entornos de ejecución de JavaScript construidos sobre V8, pero ahí es donde terminan las similitudes arquitectónicas. Deno, su lenguaje nativo, está escrito en Rust, mientras que Node.js está escrito en C++, lo que facilita su integración con V8, ya que V8 también es un proyecto en C++. Rust es el nuevo lenguaje de moda y ofrece características como seguridad de memoria y otras que lenguajes como C++ no tienen. Es realmente agradable poder trabajar en Rust, pero también dicta cómo se verán algunas de las otras dependencias en el proyecto.
4. Un Vistazo más de cerca a la Arquitectura de Deno
Node.js utiliza LibUV para E/S asíncrona y el bucle de eventos, OpenSSL para encriptación y LLHTTP para solicitudes HTTP. Deno utiliza Tokyo para E/S asíncrona, RustTLS para encriptación y Typer y Requests para solicitudes HTTP. La arquitectura de Deno incluye V8 envuelto en Rusty V8, que aísla el código C++ de V8 del resto del código Rust de Deno. Rusty V8 también permite enviar V8 precompilados. DenoOps proporciona una API para interactuar con el aislamiento y el tiempo de ejecución. Deno deploy se basa en paquetes de código abierto pero tiene un tiempo de ejecución ligeramente diferente para implementaciones en la nube.
Por ejemplo, Node.js utiliza LibUV para su E/S asíncrona y bucle de eventos, mientras que Deno utiliza Tokyo. Node.js también utiliza OpenSSL, mientras que Deno utiliza un proyecto llamado RustTLS. En el lado de HTTP, Node.js utiliza un proyecto llamado LLHTTP, mientras que Deno utiliza un par de proyectos, Typer y Requests, dependiendo de si estás en el lado del cliente o del servidor. Y luego, a nivel de DNS, tenemos TrustDNS y Deno frente a C-ARIES y Node.js.
Si nos fijamos más de cerca en la arquitectura de Deno, podemos ver aquí que tenemos el proyecto V8 envuelto en algo llamado Rusty V8. Rusty V8 son las uniones de Rust a V8. Esto es lo que aísla el código C++ de V8 de todo el otro código de Rust que está dentro de Deno. Todo lo que está fuera de V8 estará en Rust. Rusty V8 también te permite enviar V8 precompilados para que no tengas que compilarlo en tu máquina desde el código fuente, lo cual puede llevar mucho tiempo. Y luego hay algo más dentro de la biblioteca principal de Deno llamado DenoOps, que proporciona una API para interactuar con el aislamiento y el tiempo de ejecución subyacente. Todo esto está envuelto en el paquete principal de Deno. Todos estos paquetes están disponibles para que puedas tomarlos y combinarlos y crear tu propio tiempo de ejecución si realmente quieres hacerlo. Mencioné Deno deploy anteriormente. En realidad, se basa en todos los paquetes de código abierto, pero lo hace de una manera en la que el tiempo de ejecución es ligeramente diferente porque cuando ejecutas tu CLI localmente en comparación con algo que se ejecuta en la nube, habrá diferentes requisitos. Y tener un enfoque modular como este te permite aprovechar la reutilización de código mientras tienes diferentes tiempos de ejecución.
5. Deno y el Tiempo de Ejecución de Deno
El proyecto principal es un tiempo de ejecución JS mínimo envuelto en el tiempo de ejecución de Deno, que es un tiempo de ejecución de JavaScript más completo. Incluye el núcleo, Tokyo para E/S asíncrona y otras cajas que implementan varias APIs como DenoFetch, DenoCrypto y DenoWeb.
Entonces, el proyecto principal es una especie de tiempo de ejecución JS mínimo, pero probablemente no algo que realmente quieras usar. Luego, el núcleo se envuelve en otra caja llamada el tiempo de ejecución de Deno. Por lo tanto, el tiempo de ejecución de Deno es un tiempo de ejecución de JavaScript mucho más completo. Es más divertido interactuar con él. Incluye el núcleo, incluye Tokyo para la E/S asíncrona. También incluye varias otras cajas que implementan varias APIs. Algunas de ellas se muestran aquí. DenoFetch se utiliza para implementar la API Fetch, DenoCrypto realiza operaciones criptográficas, DenoWeb es para una gran compatibilidad con la plataforma web, y así sucesivamente.
6. Deno CLI y Herramientas Integradas
El Deno CLI es el ejecutable que descargas y ejecutas. Incluye el tiempo de ejecución de Deno y una herramienta integrada, proporcionando todo lo que necesitas para desarrollar y ejecutar aplicaciones Deno. Se distribuye como un único ejecutable y está disponible para Linux, macOS y Windows.
Entonces, una vez que tienes el tiempo de ejecución de Deno, vamos un paso más allá y eso es el CLI actual. Este es el ejecutable que vas a descargar y ejecutar. Deno se distribuye como un único ejecutable. Puedes obtener los paquetes desde el gestor de paquetes Rust si realmente quisieras, pero la mayoría de las personas simplemente van a descargar e instalar este ejecutable, y siempre puedes confiar en que ese ejecutable sea la forma preferida de descargar e instalar Deno.
Entonces, el CLI incluye el tiempo de ejecución, del que hablé en la diapositiva anterior, pero también incluye una herramienta integrada. Como dije antes, Deno es mucho más completo que Node.js, por lo que vas a obtener cosas como un linter, un formateador, un ejecutor de pruebas, un montón de otras cosas de serie, de las que hablaré más adelante en las diapositivas. La idea es que el CLI tenga todo lo que necesitas para desarrollar y ejecutar aplicaciones Deno. Y esto se ejecuta en Linux, macOS y Windows, y aquí tienes un enlace a la documentación de inicio si quieres seguir los pasos para descargar e instalar Deno en tu máquina.
7. Deno Biblioteca Estándar y Gestión de Dependencias
Deno tiene una biblioteca estándar con módulos de JavaScript y TypeScript mantenidos por el equipo principal. Estos módulos son auditados, garantizados para estar actualizados y funcionar bien con Deno. Pueden tener versiones independientes y están alojados en Internet. La gestión de dependencias de Deno funciona como un navegador, admitiendo solo ESM y no CommonJS. No hay package.json ni node_modules. Deno busca y almacena en caché automáticamente el código, y para aplicaciones de producción, se recomienda deno-vendor. No hay NPM, pero deno.land/x proporciona alojamiento de paquetes. Las versiones de parches se lanzan semanalmente y las versiones menores de semver se lanzan mensualmente.
Entonces, Deno también tiene una biblioteca estándar. Estos serán módulos de JavaScript y TypeScript construidos y mantenidos por el equipo principal. Son auditados y garantizados para no estar obsoletos, no ser malware, estar mantenidos y en general, auditados para asegurarse de que funcionen bien con Deno.
Diría que estos son similares a los módulos principales de Node.js en el lado de Node, como FS, HTTP, etc. La única diferencia es que estos están fuera del repositorio principal, por lo que se pueden versionar de forma independiente, lanzar de forma independiente, aunque actualmente se lanzan cuando se lanza el tiempo de ejecución principal.
Hay muchos módulos diferentes, cosas como FS, HTTP streams, cosas que estarías acostumbrado a tener en Node, UUIDs, WASI, muchas otras cosas. Realmente no hay un gestor de paquetes para Deno, pero estos módulos están alojados en Internet, por lo que si vas a esta deno.land.std, obtendrás la última versión de la biblioteca estándar, y luego también puedes versionar estos, lo cual se recomienda como se muestra en el ejemplo en la parte inferior aquí. Entonces, si quisiera importar la función de copia de la biblioteca FS, este es un ejemplo de cómo lo haría, asegurándome también de obtener la versión 0.141.0, por lo que si hay un cambio incompatible o cualquier otra cosa a medida que la biblioteca evoluciona, te garantiza obtener una versión que sabes que funciona con tu código.
Hablando de la gestión general de dependencias, funciona de manera similar a un navegador. No hay NPM. Solo admitimos ESM, no hay soporte para CommonJS. Hay CDNs como ESM.sh donde puedes cargar módulos CommonJS y se transpilarán para que puedas importarlos desde allí. No vas a tener un archivo package.json, no va a haber un directorio node modules, no hay archivo index.js. Entonces, cuando haces un require, debes especificar el nombre del archivo y no el tipo de comportamiento mágico del índice.
Entonces, si alguna vez has usado algo como Rust, siento que Deno es algo similar en el hecho de que, cuando ejecutas tu código, realmente buscará el código. Lo almacenará en caché localmente para que no tengas que seguir instalándolo. Incluso puedes hacer algo de trabajo desde un avión si es necesario. Y lo compilará automáticamente por ti. Entonces, especialmente si estás descargando TypeScript, debe ser transpilado y demás. Pero Deno hace todas estas cosas por ti detrás de escena. Y para aplicaciones de producción, recomendamos que uses un comando llamado deno-vendor, que básicamente descargará todas tus dependencias localmente. Y luego puedes agregarlas al control de origen o administrarlas como quieras en lugar de intentar instalar cosas en el momento de implementación en producción. Y como dije, no hay NPM, pero hay alojamiento de paquetes en un sitio llamado deno.land slash x. Aquí todavía estoy mostrando el ejemplo de la diapositiva anterior. Pero si reemplazas esa parte std de la URL con x, estarías usando, supongo, el equivalente de Deno de NPM. Y también hay una interfaz web. Entonces puedes navegar allí y ver todos los diferentes módulos de terceros que las personas han creado y subido. Hay un calendario de lanzamiento. Las versiones de parches se lanzan semanalmente. Las versiones menores de semver se lanzan mensualmente.
8. Deno Hello World and Tooling
Estas versiones generalmente ocurren los jueves. Aún no hay una cadencia de lanzamiento principal de Semver como la que tiene Node.js, y aún no hay un programa LTS como el que tiene Node.js, pero creo que esas cosas vendrán a medida que el proyecto madure cada vez más. Quería echar un vistazo rápido a una aplicación de Hola Mundo. Entonces, lo que estoy haciendo es importar la función serve del módulo de la biblioteca estándar HTTP de Deno, y luego crear un controlador que la función serve utiliza cada vez que recibe una solicitud. Algunas características destacadas de Deno son el enfoque en la compatibilidad con la plataforma web, la cadena de herramientas integrada, el soporte para TypeScript, el sistema de permisos y el modo de compatibilidad con el código de Node.js. Deno prefiere las API de la plataforma web cuando es posible en lugar de crear las suyas propias. Deno ha admitido las API de la plataforma web desde la versión 1, mientras que el soporte de Node.js no cumple completamente con las especificaciones. Deno tiene una variedad de herramientas integradas, incluido Deno lint para el linting.
9. Deno Tooling and Permission System
Al igual que Prettier, NVM, todas estas cosas están integradas en Deno. TypeScript es compatible de forma predeterminada y el compilador de TypeScript está incluido en el binario de Deno. SWC, el compilador web rápido, también está integrado en el ejecutable. El sistema de permisos de Deno está bloqueado por defecto, pero puedes usar banderas de CLI para otorgar permisos específicos. Deno te solicitará en tiempo de ejecución que permitas permisos que no se hayan otorgado explícitamente.
Al igual que Prettier, NVM, todas estas cosas están integradas en Deno. Con la excepción del ejecutor de pruebas, que Node sí tiene uno incorporado. Pero solo está en la última versión de Node. Creo que Node está empezando a incluir más cosas de serie. Pero por ahora, esto es más o menos cómo se ve el panorama de herramientas.
TypeScript, como mencioné, es compatible de forma predeterminada. El compilador de TypeScript está incluido en el binario de Deno. Y luego SWC, que es el compilador web rápido. Es una herramienta de JS y TypeScript escrita en Rust. Se supone que es 20 veces más rápido para aplicaciones de un solo hilo que Babel. Y creo que es como 70 veces más rápido para aplicaciones de varios hilos. Pero sí, todas estas cosas están integradas en el ejecutable. Lo usamos para transpilar y empaquetar, y cosas así. Puedes configurar el compilador de TypeScript pasando un archivo de configuración desde la CLI. Normalmente no es necesario, así que no lo recomendamos realmente. Es bueno tener una experiencia lista para usar que simplemente funciona. El sistema de permisos de Deno, por defecto, está bloqueado. No puede acceder al mundo exterior. Por lo tanto, no puede acceder al sistema de archivos, a la red, cosas así. Aquí tenemos una lista de banderas de CLI a la derecha, que puedes usar para otorgar permisos. Entonces, si quieres acceder a las variables de entorno, HR time. El tiempo de alta resolución está detrás de una bandera de CLI porque puede exponerte a ataques de temporización y cosas así. Net para acceder a la red, FFI si quieres cargar bibliotecas dinámicas. Read y write para leer y escribir en el sistema de archivos. Run te permite ejecutar procesos secundarios. Y si solo estás probando y quieres otorgar todos los permisos, entonces tienes el --allow-all, que se aliasa como -a. Por lo tanto, debes otorgar explícitamente estos permisos según sea necesario. Si algo no se otorga, Deno te solicitará que lo permitas en tiempo de ejecución.
10. Permisos de Deno y Compatibilidad con Node
Deno solicita permisos en tiempo de ejecución. Los subprocesos y FFI no están restringidos. Se pueden configurar banderas para un acceso específico. La compatibilidad con Node se puede lograr con la bandera --compat y permitir la lectura para CommonJS. Los enlaces importantes incluyen la documentación, la biblioteca estándar, los módulos de terceros, el código fuente, la comunidad de Discord y Deno Deploy.