Como aquí, Node puede hacer algo antes de que se ejecute todo el gráfico de módulos, pero no puede hacer nada entre ejecutar el código en el paquete y ejecutar el código en el módulo dependiente. Como aquí, no puede insertar nada antes de la llamada console.log en main, porque la evaluación interna está completamente controlada por VA. Es por eso que no hay un hook de evaluación pre-módulo ESN. Otra limitación de ESN es que, aunque los namespaces de ESN pueden reflejar mutaciones desde dentro del exportador, no pueden ser mutados desde el importador. La mutabilidad está mandatada por el lenguaje y controlada por el motor de JavaScript, no por el embebedor del motor de JavaScript. Así que, por ejemplo, aquí tenemos un módulo que muta la variable count. Si intentamos actualizar el count a 5 desde el módulo principal, la mutación no tiene efecto, porque el namespace es inmutable según el lenguaje. Pero si invocamos el método ink, que muta el count desde dentro de ese módulo, esto se reflejará en el objeto namespace del módulo.
Además, en este caso, el embebedor no puede controlar la mutabilidad del namespace. Si deseas hacer alguna personalización del namespace, debe hacerse modificando el código fuente en el hook de carga. También tenemos algunas nuevas características del lenguaje que cambian cómo se realizan las evaluaciones. Por ejemplo, desde 2004, Node soporta la propuesta de importación basada en fuente de Stage 3 que permite a los usuarios personalizar la evaluación de Wazen en ESN usando la API de WebAssembly. Otra característica próxima de Stage 3 es la evaluación diferida. Esto se está integrando actualmente en Node detrás de una bandera de V8. Así que si tienes un módulo como HeavyJS aquí, que tiene muchas inicializaciones para ejecutar, o simplemente tiene un gran gráfico de dependencias que contiene muchas bibliotecas que no usas, si sus exportaciones solo serán realmente necesarias cuando se llame a la función, puedes usar la palabra clave defer para diferir la evaluación de los módulos menos usados para que solo se evalúen bajo demanda cuando se accede a la propiedad. Con esto puedes reducir el tiempo de inicio del código y mantener el uso de memoria bajo.
Así que eso fue un recorrido por la importación de ESN en Node. Volviendo al cuestionario inicial, creo que ahora estará claro lo que está sucediendo aquí. En un fragmento, primero encontraremos el error de resolución porque ese es el primer paso. Si solucionamos la resolución, Node comenzará a intentar cargar el código y analizar las dependencias y el módulo con error de sintaxis fallará a continuación. Después de eso, si solucionamos eso, pasamos a la instanciación, nos encontramos con el error de la exportación no coincidente. Finalmente, encontraremos el error de la dependencia del módulo porque la evaluación ocurre en la última etapa. Así que una última cosa, hablamos sobre cómo ESN cobra vida en Node, pero ¿qué lo mantiene vivo? ¿Cuándo desaparecerá? En este caso, la mayor parte de la complejidad proviene de este requisito de idempotencia en la especificación del lenguaje. Cuando la solicitud del módulo es la misma, el módulo devuelto por el embebedor debe ser el mismo. Por ejemplo, aquí si tenemos un módulo con estado que exporta algo que muta su estado interno y en otro módulo lo cargamos y lo liberamos. Después de cierta recolección de basura, el estado debería haber desaparecido. Pero en realidad, según la especificación, algún tiempo después, incluso si la variable original parece desaparecer, cuando regresa, al ser cargada nuevamente, todavía necesita mantener el estado original. Así que como puedes imaginar, para lograr esto, Node necesita mantener varios cachés internos. Y estas referencias internas pueden hacer que las herramientas y los marcos apunten a fugas cuando implementan, por ejemplo, recarga en caliente de ESN en Node. Así que para abordar este problema, hay una API de limpieza de caché de módulos que se está trabajando actualmente.
Comments