Explore cómo funciona el método require() en Node.js
Casi cualquier desarrollador de Node.js puede decirte qué hace la función require(), pero ¿cuántos de nosotros sabemos realmente cómo funciona? Lo usamos todos los días para cargar bibliotecas y módulos, pero su comportamiento es un misterio para nosotros.
Por curiosidad, indagué en el código central del nodo para descubrir qué estaba pasando bajo el capó. Pero esta no es una función única. Encontré module.js en el sistema de módulos del nodo. Este archivo contiene un módulo central sorprendentemente poderoso y relativamente desconocido que controla la carga, compilación y almacenamiento en caché de cada archivo. La aparición de require() es sólo la punta del iceberg.
module.jsfunction Módulo(id, padre) {
this.id = id
this.exports = {}; > this.parent = parent;
// ...module.js desempeña principalmente dos funciones dentro de Node.js. Primero, proporciona una base para todos los módulos de Node.js. Cada archivo es una nueva instancia de un módulo base que persiste incluso después de que se haya ejecutado el archivo. Es por eso que podemos adjuntar atributos a module.exports y devolverlos cuando sea necesario.
La segunda tarea principal de este módulo es manejar el mecanismo de carga del módulo de node. La función de operación independiente "require" que utilizamos es en realidad un concepto abstracto de module.require, que en sí mismo es solo una simple encapsulación de la función Module._load. Este método de carga maneja la carga real de cada archivo y comienza nuestro viaje allí.
Module._load
Module._load = function(request, parent, isMain) {
// 1. Verifique Module._cache para el módulo almacenado en caché.
// 2. Crea una nueva instancia de módulo si el caché está vacío.
// 3. Guárdalo en el caché.
// 4. Llama module.load() con el nombre de archivo proporcionado.
// Esto llamará a module.compile() después de leer el contenido del archivo.
// 5. Si hubo un error cargando/analizando el archivo,
// elimina el módulo defectuoso del caché
// 6. devuelve module.exports
}; Responsable Cargar nuevos módulos y administrar el caché del módulo. El almacenamiento en caché de cada módulo cargado reduce la cantidad de lecturas de archivos redundantes y puede acelerar significativamente su aplicación. Además, las instancias de módulos compartidos permiten que las características únicas de los módulos permanezcan en el proyecto.
Si un módulo no existe en la caché, Module._load creará un nuevo módulo base para ese archivo. Luego le dice al módulo que lea el contenido de los nuevos archivos antes de enviarlos a module._compile.
[1]
Si observa el paso 6 anterior, verá que module.exports ha sido devuelto al usuario. Es por eso que cuando defines una interfaz pública para usar, usas exports y module.exports, porque Module._load luego devolverá el contenido requerido. Me sorprende que no haya más funciones aquí, pero sería bueno si las hubiera.
module._compile
Module.prototype._compile = function(content, filename) { // 1. Cree la función require independiente que llame a module.require // 2. Adjunte. otros métodos auxiliares para requerir. // 3. Envuelve el código JS en una función que proporciona nuestras variables require, // módulo, etc. localmente en el alcance del módulo. // 4. Ejecute esa función}; sucede lugar. Primero, se crea una función requerida independiente especial para este módulo. Esta es una característica que todos necesitamos y con la que estamos familiarizados. La función en sí es solo un paquete en Module.require, y también contiene algunos métodos auxiliares poco conocidos que son fáciles de usar para nosotros:
·Require(): carga un módulo externo
· require.resolve(): resuelve el nombre de un módulo en su ruta absoluta
· require.main: módulo principal
· require.cache: todos los módulos almacenados en caché
p>
· require.extensions: Los métodos de compilación disponibles para cada tipo de archivo válido según su extensión
Una vez que require esté listo, todo el código fuente cargado se encapsulará en un nuevo La función puede aceptar requisitos, módulos, exportaciones y todas las demás variables expuestas como parámetros. Esta es una función creada únicamente para encapsular el módulo con el fin de evitar conflictos con el entorno Node.js.
(function (exports, require, module, __filename, __dirname) {
// ¡TU CÓDIGO INYECTADO AQUÍ!
}); Se ejecuta de forma sincrónica, por lo que la llamada a Module._load solo puede esperar hasta el final de este código y devolver module.exprts al usuario.
Conclusión
Entonces, hemos entendido todo el código de require y tenemos una comprensión preliminar de cómo funciona.
Si has seguido todo esto, entonces estás listo para el secreto final: require('module'). Así es, el sistema de módulos en sí se puede cargar a través del sistema de módulos. Comienzo. Esto puede sonar extraño, pero permite al usuario interactuar con el sistema de carga de módulos sin tener que profundizar en el núcleo de Node.js. Los módulos populares se construyen así. [2]
Si desea obtener más información, consulte usted mismo el código fuente de module.js. Hay suficientes cosas como para darte dolor de cabeza por un tiempo.
El primero que pueda decirme qué es NODE_MODULE_CONTEXTS y por qué se agrega obtendrá puntos de bonificación :)
[1] El método module._compile solo se usa para ejecutar archivos JSON que deben pasarse. JSON .parse() analiza y devuelve
[2] Sin embargo, ambos módulos están integrados en métodos de módulos privados como Module._resolveLookupPaths y Module._findPath. ¿Puedes pensar que esto no es mucho mejor?
Casi cualquier desarrollador de Node.js puede decirle qué hace la función require(), pero ¿cuántos de nosotros sabemos realmente cómo funciona? La usamos todos los días para cargar bibliotecas y módulos, pero su comportamiento era un misterio para nosotros.
Por curiosidad, busqué en el código central del nodo para descubrir qué estaba pasando bajo el capó, pero no era una función única, encontré module.js en el sistema de módulos del nodo. El archivo contiene un módulo central sorprendentemente poderoso y relativamente desconocido que controla la carga, compilación y almacenamiento en caché de cada archivo. Resultó ser require(), solo la punta del iceberg
module.jsfunction Module(. id, padre) {
this.id = id
this.exports = {};
this.parent =
// ... module.js desempeña principalmente dos funciones dentro de Node.js. Primero, sirve a todos los módulos de Node.js. Proporciona una base. Cada archivo es una nueva instancia del módulo base y persiste incluso después de que el archivo haya terminado. Se ha ejecutado. Es por eso que podemos adjuntar atributos a module.exports y devolverlos cuando sea necesario. p>
La segunda tarea principal de este módulo es manejar el mecanismo de carga del módulo de node. La función que utilizamos es en realidad un concepto abstracto de module.require, que en sí mismo es solo un módulo simple sobre Module. Un contenedor para la función ._load. Este método de carga maneja la carga real de cada archivo y comienza nuestro viaje allí.
Module._load
Module._load = function(request, parent, isMain) {
// 1. Verifique Module._cache para el módulo almacenado en caché.
// 2. Crea una nueva instancia de módulo si el caché está vacío.
// 3. Guárdalo en el caché.
// 4. Llama module.load() con el nombre de archivo proporcionado.
// Esto llamará a module.compile() después de leer el contenido del archivo.
// 5. Si hubo un error cargando/analizando el archivo,
// elimina el módulo defectuoso del caché
// 6. devuelve module.exports
}; Responsable Cargar nuevos módulos y administrar el caché del módulo. El almacenamiento en caché de cada módulo cargado reduce la cantidad de lecturas de archivos redundantes y puede acelerar significativamente su aplicación. Además, las instancias de módulos compartidos permiten que las características únicas de los módulos permanezcan en el proyecto.
Si un módulo no existe en la caché, Module._load creará un nuevo módulo base para ese archivo. Luego le dice al módulo que lea el contenido de los nuevos archivos antes de enviarlos a module._compile. [1]
Si observa el paso 6 anterior, verá que module.exports ha sido devuelto al usuario. Es por eso que cuando defines una interfaz pública para usar, usas exports y module.exports, porque Module._load luego devolverá el contenido requerido. Me sorprende que no haya más funciones aquí, pero sería bueno si las hubiera.
module._compile
Module.prototype._compile = function(content, filename) { // 1. Cree la función require independiente que llame a module.require // 2. Adjunte. otros métodos auxiliares para requerir. // 3. Envuelve el código JS en una función que proporciona nuestras variables require, // módulo, etc. localmente en el alcance del módulo. // 4. Ejecute esa función}; sucede lugar. Primero, se crea una función requerida independiente especial para este módulo. Esta es una característica que todos necesitamos y con la que estamos familiarizados.
La función en sí es solo un paquete en Module.require, y también contiene algunos métodos auxiliares poco conocidos que son fáciles de usar para nosotros:
·Require(): carga un módulo externo
· require.resolve(): resuelve el nombre de un módulo en su ruta absoluta
· require.main: módulo principal
· require.cache: todos los módulos almacenados en caché
p>
· require.extensions: Los métodos de compilación disponibles para cada tipo de archivo válido según su extensión
Una vez que require esté listo, todo el código fuente cargado se encapsulará en un nuevo La función puede aceptar requisitos, módulos, exportaciones y todas las demás variables expuestas como parámetros. Esta es una función creada únicamente para encapsular el módulo con el fin de evitar conflictos con el entorno Node.js.
(function (exports, require, module, __filename, __dirname) {
// ¡TU CÓDIGO INYECTADO AQUÍ!
}); Se ejecuta de forma sincrónica, por lo que la llamada a Module._load solo puede esperar hasta el final de este código y devolver module.exprts al usuario.
Conclusión
Entonces, hemos entendido todo el código de require y tenemos una comprensión preliminar de cómo funciona.
Si has seguido todo esto, entonces estás listo para el secreto final: require('module'). Así es, el sistema de módulos en sí se puede cargar a través del sistema de módulos. Comienzo. Esto puede sonar extraño, pero permite al usuario interactuar con el sistema de carga de módulos sin tener que profundizar en el núcleo de Node.js. Los módulos populares se construyen así. [2]
Si desea obtener más información, consulte usted mismo el código fuente de module.js. Hay suficientes cosas como para darte dolor de cabeza por un tiempo. El primero que pueda decirme qué es NODE_MODULE_CONTEXTS y por qué se agrega puede obtener puntos de bonificación :)
[1] El método module._compile solo se usa para ejecutar archivos JSON que deben pasarse. a través de JSON .parse() analiza y devuelve
[2] Sin embargo, ambos módulos están integrados en métodos de módulos privados como Module._resolveLookupPaths y Module._findPath. ¿Puedes pensar que esto no es mucho mejor?