Construyendo un Entorno de Ejecución Node.js para el Navegador

Rate this content
Bookmark

Recorreremos lo que se necesita para construir un entorno de ejecución Node.js para el navegador, los desafíos que descubrimos en el camino y las soluciones que construimos para esos desafíos.

13 min
15 Nov, 2023

AI Generated Video Summary

Esta charla discute los desafíos y la colaboración involucrados en la construcción de Nodebox, un entorno de ejecución compatible con Node.js para el navegador. Proporciona una visión general de cómo funciona Nodebooks, incluyendo el administrador principal, las vistas previas y los trabajadores web. La charla también cubre la simplicidad y velocidad de lectura desde el sistema de archivos en Nodebooks. Destaca la complejidad de implementar el soporte HTTP y la simulación de WebSocket en Nodebox. Por último, menciona la capacidad de construir un servidor web utilizando Nodebox y proporciona información sobre las plantillas disponibles.

1. Construyendo Nodebox: Desafíos y Colaboración

Short description:

Hola, soy Jasper. Hablaré sobre cómo construimos Nodebox, un entorno de ejecución compatible con Node.js para el navegador. Necesitábamos construir un sistema de archivos, un servidor HTTP, soporte para websockets, módulos y la capacidad de buscar módulos NPM. Tuvimos ayuda de las bibliotecas existentes en el ecosistema de Browserify.

Hola, soy Jasper. Soy un ingeniero de personal en Codesoundbox, y voy a dar una charla sobre cómo construimos nuestro entorno de ejecución compatible con Node.js para el navegador llamado Nodebox. Entonces, ¿por qué realmente construimos un entorno de ejecución compatible con Node.js para el navegador? Queríamos construir un entorno de ejecución compatible con Node.js porque queríamos permitir que nuestra biblioteca de juegos, Sandpack, ejecute pequeños proyectos. Como por ejemplo un pequeño ejemplo de Next.js, un ejemplo de feed, o una aplicación Next.pressjs. Obviamente para los propósitos de documentación.

¿Y qué necesitábamos construir para hacer esto posible? Hay muchas cosas que entran en Node.js. Por ejemplo, tuvimos que construir un sistema de archivos, un servidor HTTP y soporte para websockets, tuvimos que construir módulos, tuvimos que ser capaces de buscar módulos NPM. También tuvimos que asegurarnos de que teníamos soporte para procesos hijos, ya que la mayoría de las bibliotecas y frameworks dependen mucho de eso. Y también hay muchas más bibliotecas más pequeñas y otras bibliotecas estándar en Node.js que tuvimos que soportar para hacer todo esto funcionar. Así que en realidad tuvimos mucha ayuda de las bibliotecas existentes, porque hay muchas cosas por ahí del ecosistema de Browserify. Por ejemplo, está assert, y está como zlib. También está un buffer y eventos, o decodificador de cadena de ruta, como utilidades de URL. Stream legible por el equipo de Node, que nos ayuda a construir soporte para streams. Y luego también está como crypto, y un montón

2. Resumen de Nodebooks y Sistema de Archivos

Short description:

Así que un resumen general de cómo funciona realmente Nodebooks. Tenemos un administrador principal que controla todo en nuestro entorno virtual. Genera procesos, imitando los procesos reales de Node. También tenemos vistas previas, que actúan como un servidor HTTP. Nuestros procesos Node son trabajadores web con su propio proceso contenido. Utilizamos trabajadores web para inicializar cada trabajador y hacer el trabajo de inicialización de construcción del árbol del sistema de archivos, cargar archivos de ensamblaje web y esperar a que termine. Una vez que el trabajador está listo, lo enviamos de vuelta al principal y podemos ejecutar comandos como Next.js. Envolvemos el módulo en nuestro propio global para hacerle creer que se está ejecutando en un entorno de nodo. Nuestro sistema de archivos funciona con el proceso principal teniendo todo el estado y los trabajadores teniendo consistencia eventual. Al escribir en el sistema de archivos, la escritura se sincroniza y se envía al proceso principal para sincronizarla en todo el estado de la aplicación.

y otras que no están listadas en esta diapositiva. Así que un resumen general de cómo funciona realmente Nodebooks. Así que tenemos nuestro administrador principal, que controla todo en nuestro entorno virtual. Y genera procesos, que son procesos reales de Node, o intentan ser procesos de Node, los imitan. Y luego también tenemos vistas previas, que son algo así como tu servidor HTTP, que pasa por nuestro administrador de vistas previas, que construimos, que luego inicia iframes para imitar este comportamiento del servidor HTTP. Y nuestros procesos Node son en realidad web workers, que también tienen su propio proceso contenido similar a cómo funciona Node. Y entonces, ¿cómo funciona un proceso Node en nuestro entorno? Como dije antes, utilizamos web workers. Para hacer esto, inicializamos cada trabajador enviando un buffer del sistema de archivos y variables de entorno y un montón de otras pequeñas opciones de configuración que tenemos en Nodebox. Bueno, una vez que esto sucede, el trabajador se pone en marcha y comienza a hacer su trabajo de inicialización, que es construir el árbol del sistema de archivos, cargar algunos archivos de ensamblaje web que utilizamos por ejemplo, para transpilar nuestro código o algunas cosas como probablemente la compresión, que realmente no existe en el navegador en este momento. Y también tenemos cosas como esperar a que termine al final. Y luego entramos en la carga del resto de las cosas. Entonces, una vez que el trabajador está listo, lo enviamos de vuelta al principal. Y una vez que está en el principal, el principal sabe que nuestro trabajador está listo. Y ahora, podemos hacer como ejecutar un comando. Por ejemplo, ejecutar Next.js es tan simple como pasar el comando JSON next y luego se inicia todo un servidor Next.js. Hace esto yendo a nuestros nodos modules y resolviendo el binario next que en realidad es solo un archivo JavaScript al final. Entonces, resolvemos eso que termina siendo como .bin slash next y luego tiene un enlace simbólico a slash node module slash next slash CLI.MJS o algo así. Y luego ejecutamos ese script real como node, el archivo resuelto y luego lo pasamos como argumentos a nuestro módulo. Y luego lo usamos para evaluar el módulo. Cómo hacemos eso es envolviendo nuestro módulo en nuestro propio global que construimos que contiene la mayoría de los globales, los nodos modules esperan como el módulo, global require hay un par de otras cosas del módulo ES y luego global this que es todo diferente del navegador y tratamos de hacerle creer que se está ejecutando en un entorno de nodo en lugar del navegador real. Así que también establecemos ciertos globales del navegador en indefinido o nulo. Y luego lo ejecutamos en una función. Lo envolvemos en una función con nuestros argumentos globales. Así que el código cree que estos son nuevos globales en lugar de los globales reales que tiene el navegador. Y eso también lo hacemos aplicar donde anulamos los discos para que sean nuestros discos globales en lugar de los discos del navegador. Así que realmente cree que está dentro de un entorno de nodo mientras todavía se está ejecutando dentro de un navegador. Entonces, ¿cómo funciona nuestro sistema de archivos? Nuestro sistema de archivos funciona de tal manera que nuestro proceso principal tiene el estado completo del sistema de archivos y todos nuestros trabajadores tienen consistencia eventual. Por ejemplo, aquí tenemos un ejemplo de cómo se escribe en un sistema de archivos. Entonces en el módulo, tienes importfs y luego llamas a fs.write. Esa escritura luego se envía a nuestro estado del sistema de archivos que instantáneamente lo sincroniza en su propio estado y luego envía un mensaje a nuestro bus de trabajadores al proceso principal para decir que he escrito algún archivo. ¿Puedes sincronizarlo en todo nuestro estado de la aplicación? Y luego el estado principal del sistema de archivos también recibe eso, actualiza su estado interno y luego

3. Lectura del Sistema de Archivos

Short description:

En Nodebooks, la lectura del sistema de archivos es simple y rápida. Cada módulo tiene acceso al estado completo del sistema de archivos y puede recuperar archivos instantáneamente utilizando la función fs.read().

lo emite a todos los demás trabajadores. Así que en este caso solo hay un trabajador que recibe este mensaje y luego también actualiza su propio estado del sistema de archivos. Así que si ahora hubiera un segundo módulo en Worker2 que intenta leer ese archivo, obtendría el estado más reciente. Entonces, ¿cómo funciona la lectura? La lectura es mucho más simple porque ya tienes el estado completo del sistema de archivos en tu proceso. Así que es solo tu módulo tiene la biblioteca estándar del sistema de archivos y luego haces fs.read() y luego simplemente lo busca instantáneamente en un mapa en el estado del sistema de archivos y lo resuelve sin pasar ningún mensaje ni nada.

4. Soporte HTTP y Simulación de WebSocket

Short description:

Y luego también tenemos soporte HTTP. Es más complicado que el sistema de archivos. Iniciamos un servidor HTTP simple en el puerto 3000. Nuestro entorno de Nodebox envía un mensaje a nuestro trabajador para iniciar el servidor. El administrador de vista previa abre un iframe con un relevo de vista previa. El relevo inicializa un trabajador de servicio. El administrador de vista previa envía el mensaje listo a Sandpack, que genera otro iframe de vista previa. Las solicitudes pasan por el trabajador de servicio, el relevo, el administrador de vista previa y el trabajador. Las respuestas se envían de vuelta a través del mismo flujo. El soporte de WebSocket se proporciona a través de un WebSocket simulado.

Es instantáneo. Es increíblemente rápido. Y luego también tenemos soporte HTTP. Esto es bastante más complicado que el sistema de archivos. Así que empecemos con el inicio de un simple servidor HTTP. Por ejemplo en el puerto 3000. Así que tenemos nuestro módulo que como tienes el código estándar de servidor HTTP y luego llamas a httpserver.listen() con un puerto al final. Y una vez que haces eso, nuestro entorno de Nodebox sale del módulo y luego envía un mensaje a nuestro trabajador para decir que inicie el servidor HTTP en el puerto 3000. Lo recibe, lo pasa al administrador de vista previa que gestiona todas las vistas previas y servidores que podrían ser comparados con los sockets en un sistema operativo. Y luego tú y luego el administrador de vista previa dice abrir un iframe para registrar este puerto. Ese iframe contiene lo que llamamos un relevo de vista previa que tiene un nombre de dominio único con algún script de inicialización que construimos en Code Sandbox. Ese script de inicialización inicia un trabajador de servicio que luego escucha las solicitudes que entran y una vez que está listo, dice que está listo para recibir solicitudes. Y luego volvemos al administrador de vista previa con ese mensaje listo a través de nuestro relevo y luego el administrador de vista previa envía esto a Sandpack que en realidad genera otro iframe de vista previa que en realidad muestra tu aplicación. El relevo tiene este script de inicialización y no muestra nada. El marco de vista previa en realidad contiene tu aplicación. Y una vez que ha hecho eso, vuelve a los trabajadores para decir que está listo y luego obtienes en tu módulo como un evento de escucha en tu HttpServer. Y es igual que Node.js regular. ¿Cómo funcionan las solicitudes en esta configuración? Tienes tu marco de vista previa que contiene tu aplicación. Haces una HttpRequest, por ejemplo, cargando el index.html. Pasa a través del trabajador de servicio que intercepta esa solicitud y luego le dice al relevo, he recibido una solicitud. El relevo luego le dice al administrador de vista previa, hay una solicitud aquí para que la manejes. El administrador de vista previa sabe dónde se está ejecutando el servidor en nuestra red de trabajadores. Así que pasa por el principal, luego el principal lo envía al trabajador. Ese trabajador luego emite un evento de solicitud a tu módulo y luego lo manejas como un nodo regular y luego eventualmente obtendrás una respuesta. Esa respuesta luego pasa de nuevo a través de ese trabajador, de vuelta al principal, de vuelta al administrador de vista previa, luego el administrador de vista previa lo envía de nuevo al relevo, y hay un ID único para esto, por lo que se rastrea en todo el gráfico. Y luego una vez que el relevo de vista previa tiene esta respuesta, le dice al trabajador de servicio, tengo una respuesta para tu solicitud con ID algo. Y luego envía esa respuesta a tu marco de vista previa, como lo harías con un trabajador de servicio. Solo que aquí pasa por un montón de trabajadores y relevos a un servidor simulado en lugar de un servidor real. Pero luego también tenemos soporte para WebSocket, que hace algo similar. Simula el WebSocket real al sobrescribir el global con algo que llamamos un WebSocket simulado, y lo construimos completamente. Hay códigos y simulaciones donde hemos sobrescrito cada método de este WebSocket para ser compatible con NodeBox en lugar de usar WebSockets reales. Esto solo ocurre cuando es el host local o la IP local, entonces utiliza la lógica de simulación, y de lo contrario simplemente utiliza un verdadero WebSocket, porque podrías querer conectarte a un servidor web real, incluso en tu

5. Soporte de WebSocket y Construcción de un Servidor Web

Short description:

Veamos cómo funciona el soporte de WebSocket en NodeBox. Comienza desde un marco de vista previa y pasa por el trabajador de servicio, el relevo y el administrador. Con todos estos bloques de construcción, puedes construir tu propio servidor web. Pruébalo en NodeBox.codesandbox.io. Tenemos plantillas para Node.js, Next.js, Vite, React, Vue, Spelt y Astro. Conéctate conmigo en Twitter en Jasper D'Amour y encuentra Codesandbox en Codesandbox.

pequeños proyectos de masterclass. Así que veamos cómo funciona. De nuevo, empezamos desde, por ejemplo, un marco de vista previa que dice, quiero enviar un mensaje de WebSocket. Y luego pasa por el trabajador de servicio de nuevo, de la misma manera que una solicitud. De hecho, el primer mensaje en un WebSocket es una solicitud de actualización. Y eso hace exactamente lo mismo que antes. Pero ahora queremos enviar un mensaje. Así que lo enviamos a través de un trabajador de servicio. El trabajador de servicio lo devuelve al relevo, y de vuelta al administrador, sabe dónde se está ejecutando ese servidor, porque primero hiciste una solicitud para iniciar un WebSocket, y luego el módulo lo manejará. Y luego respondes a él, por ejemplo, con otro WebSocket.send. Luego pasas por el trabajador, a través de main de nuevo, administrador de vista previa, relevo de vista previa, igual que antes, y luego emite esto de nuevo al trabajador de servicio, de vuelta al marco de vista. Y ahora básicamente también tenemos soporte de WebSocket.

Y con todo eso, tienes un servidor web bastante básico en funcionamiento. Por ejemplo, aquí tienes un simple hola mundo. Incluso imprime en la consola que el servidor está funcionando cuando se realiza la escucha. Con todos estos bloques de construcción, puedes construir algo como esto tú mismo. Teóricamente es idéntico a cómo funciona NodeBox. Puedes probar esto, puedes probar esto en NodeBox.codesandbox.io. Tenemos un montón de plantillas construidas sobre Sandpack con las que puedes jugar, como Node.js, Next.js, Vite, React en Vite, React en nuestro entorno de navegador Sandpack. Vue en Vite, pero también Vue en nuestro navegador entorno Sandbox. Y luego tienes, como, Spelt de nuevo a los entornos, y luego Astro que también apoyamos. Y puedes jugar con cualquier cosa que sea compatible con Node y ver si funciona. Si no funciona, siempre puedes abrir un ticket en GitHub para que lo arreglemos.

¡Gracias por escuchar! Puedes encontrarme en Twitter en Jasper D'Amour. Y también puedes encontrar Codesandbox en Twitter en Codesandbox. De nuevo, puedes jugar con todo esto en NodeBox.Codesandbox.com, y gracias de nuevo por escuchar!

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

JSNation 2022JSNation 2022
28 min
Full Stack Documentation
Interactive web-based tutorials have become a staple of front end frameworks, and it's easy to see why — developers love being able to try out new tools without the hassle of installing packages or cloning repos.But in the age of full stack meta-frameworks like Next, Remix and SvelteKit, these tutorials only go so far. In this talk, we'll look at how we on the Svelte team are using cutting edge web technology to rethink how we teach each other the tools of our trade.
React Summit US 2023React Summit US 2023
32 min
Gateway to React: The React.dev Story
A behind the scenes look at the design and development of the all-new React docs at react.dev. The new react.dev launched this year introducing new methodologies like challenges and interactive sandboxes and subtle inclusivity features, like "international tone" and culturally agnostic examples. Not only have the new docs changed how people learn React, they've inspired how we think about developer education as a community. In this talk, you will learn how the React team and some ambitious community members made the "React docs rock" for a generation of front end developers and how these new patterns and established techniques can be applied in your favorite projects.
React Finland 2021React Finland 2021
27 min
Opensource Documentation—Tales from React and React Native
Documentation is often your community's first point of contact with your project and their daily companion at work. So why is documentation the last thing that gets done, and how can we do it better? This talk shares how important documentation is for React and React Native and how you can invest in or contribute to making your favourite project's docs to build a thriving community
React Finland 2021React Finland 2021
18 min
Documenting components with stories
Most documentation systems focus on text content of one form or another: WYSIWYG editors, markdown, code comments, and so forth. Storybook, the industry-standard component workshop, takes a very different approach, focusing instead on component examples, or stories.
In this demo, I will introduce an open format called Component Story Format (CSF).
I will show how CSF can be used used to create interactive docs in Storybook, including auto-generated DocsPage and freeform MDX documentation. Storybook Docs is a convenient way to build a living production design system.
I will then show how CSF stories can be used create novel forms of documentation, such as multiplayer collaborative docs, interactive design prototypes, and even behavioral documentation via tests.
Finally, I will present the current status and outline a roadmap of improvements that are on their way in the coming months.
TypeScript Congress 2022TypeScript Congress 2022
25 min
TypeScript for Library Authors: Harnessing the Power of TypeScript for DX
Using real-life open-source examples, we'll explore the power of TypeScript to improve your users' experience. We'll cover best practices for library authors, as well as tips and tricks for how to take a library to the next level. This talk will cover: 
- how to leverage the type inference to provide help to your users; - using types to reduce the need and complexity of your documentation - for example, using function overloads, string literal types, and helper (no-op) functions; - setting up testing to ensure your library works (and your types do too!) with tools like tsd and expect-type; - treating types as an API and reducing breaking changes whilst shipping enhancements; - I'd draw on my experience with libraries like nuxt3, sanity-typed-queries and typed-vuex and show what we managed to do and what I'd do differently in future. 

React Advanced Conference 2021React Advanced Conference 2021
24 min
The Legendary Fountain of Truth: Componentize Your Documentation!
"In Space, No One Can Hear You Scream." The same goes for your super-brand-new-revolutionary project: Documentation is the key to get people speaking about it.Building well-fitted documentation can be tricky. Having it updated each time you release a new feature had to be a challenging part of your adventure. We tried many things to prevent the gap between doc and code: code-generated documentation, live examples a-la-Storybook, REPL...It's time for a new era of documentation where people-oriented content lives along with code examples: this talk will guide you from Documentation Best Practices – covered from years of FOSS collaborative documentation – to the new fancy world of Components in Markdown: MDX, MDJS, MD Vite, and all.Let's build shiny documentation for brilliant people!