Una introducción a los sistemas de módulos en JavaScript

Una introducción a los sistemas de módulos en JavaScript

El concepto de módulos proviene del paradigma de programación modular. Este paradigma propone que el software debe estar compuesto por componentes separados e intercambiables llamados 'módulos' al dividir las funciones del programa en archivos independientes que pueden funcionar por separado o acoplados en una aplicación.





MAKEUSEOF VÍDEO DEL DÍA

Un módulo es un archivo independiente que encapsula código para implementar ciertas funciones y promover la reutilización y la organización.





Aquí cubrirá los sistemas de módulos que se usan en las aplicaciones de JavaScript, incluido el patrón del módulo, el sistema de módulos CommonJS que se usa en la mayoría de las aplicaciones de Node.js y el sistema de módulos ES6.





El patrón del módulo

Antes de la introducción de los módulos nativos de JavaScript, el patrón de diseño de módulos se usaba como un sistema de módulos para abarcar variables y funciones en un solo archivo.

Esto se implementó utilizando expresiones de función invocadas inmediatamente, conocidas popularmente como IIFE. Un IIFE es una función no reutilizable que se ejecuta tan pronto como se crea.



Aquí está la estructura básica de un IIFE:

(function () { 
//code here
})();

(() => {
//code here
})();

(async () => {
//code here
})();

El bloque de código anterior describe los IIFE utilizados en tres contextos diferentes.





Los IIFE se usaron porque las variables declaradas dentro de una función tienen el alcance de la función, por lo que solo se puede acceder a ellas dentro de la función, y porque las funciones le permiten devolver datos (haciéndolos accesibles públicamente).

Por ejemplo:





const foo = (function () { 
const sayName = (name) => {
console.log(`Hey, my name is ${name}`);
};
//Exposing the variables
return {
callSayName: (name) => sayName(name),
};
})();
//Accessing exposed methods
foo.callSayName("Bar");

El bloque de código anterior es un ejemplo de cómo se crearon los módulos antes de la introducción de los módulos JavaScript nativos.

El bloque de código anterior contiene un IIFE. El IIFE contiene una función que hace accesible devolviéndola. Todas las variables declaradas en el IIFE están protegidas del ámbito global. Así, el método ( decirNombre ) solo es accesible a través de la función pública, llamarDigaNombre .

Observe que el IIFE se guarda en una variable, Foo . Esto se debe a que, sin una variable que apunte a su ubicación en la memoria, las variables serán inaccesibles después de que se ejecute el script. Este patrón es posible debido a Cierres de JavaScript .

El sistema de módulos CommonJS

El sistema de módulos CommonJS es un formato de módulo definido por el grupo CommonJS para resolver problemas de alcance de JavaScript mediante la ejecución de cada módulo en su espacio de nombres.

El sistema de módulos CommonJS funciona al obligar a los módulos a exportar explícitamente las variables que desean exponer a otros módulos.

Este sistema de módulos fue creado para JavaScript del lado del servidor (Node.js) y, como tal, no se admite de forma predeterminada en los navegadores.

Para implementar módulos CommonJS en su proyecto, primero debe inicializar NPM en su aplicación ejecutando:

npm init -y 

Las variables exportadas siguiendo el sistema de módulos CommonJS se pueden importar así:

//randomModule.js 
//installed package
const installedImport = require("package-name");
//local module
const localImport = require("/path-to-module");

Los módulos se importan en CommonJS usando el requerir instrucción, que lee un archivo JavaScript, ejecuta el archivo leído y devuelve el exportaciones objeto. los exportaciones El objeto contiene todas las exportaciones disponibles en el módulo.

Puede exportar una variable siguiendo el sistema de módulos CommonJS utilizando exportaciones con nombre o exportaciones predeterminadas.

Exportaciones con nombre

Las exportaciones con nombre son exportaciones identificadas por los nombres que se les asignaron. Las exportaciones con nombre permiten múltiples exportaciones por módulo, a diferencia de las exportaciones predeterminadas.

Por ejemplo:

//main.js 
exports.myExport = function () {
console.log("This is an example of a named export");
};
exports.anotherExport = function () {
console.log("This is another example of a named export");
};

En el bloque de código anterior, está exportando dos funciones con nombre ( miexportación y otroExportar ) uniéndolos a la exportaciones objeto.

Del mismo modo, puede exportar las funciones de esta manera:

const myExport = function () { 
console.log("This is an example of a named export");
};
const anotherExport = function () {
console.log("This is another example of a named export");
};
module.exports = {
myExport,
anotherExport,
};

En el bloque de código anterior, establece el exportaciones objeto a las funciones nombradas. Sólo puede asignar el exportaciones objeto a un nuevo objeto a través de la módulo objeto.

Su código arrojaría un error si intentara hacerlo de esta manera:

//wrong way 
exports = {
myExport,
anotherExport,
};

Hay dos formas de importar exportaciones con nombre:

1. Importe todas las exportaciones como un solo objeto y acceda a ellas por separado usando la notación de punto .

Por ejemplo:

//otherModule.js 
const foo = require("./main");
foo.myExport();
foo.anotherExport();

2. Desestructurar las exportaciones del exportaciones objeto.

Por ejemplo:

//otherModule.js 
const { myExport, anotherExport } = require("./main");
myExport();
anotherExport();

Una cosa es común en todos los métodos de importación, se deben importar con los mismos nombres con los que se exportaron.

Exportaciones predeterminadas

Una exportación predeterminada es una exportación identificada con cualquier nombre de su elección. Solo puede tener una exportación predeterminada por módulo.

Por ejemplo:

//main.js 
class Foo {
bar() {
console.log("This is an example of a default export");
}
}
module.exports = Foo;

En el bloque de código anterior, está exportando una clase ( Foo ) reasignando el exportaciones objetarlo.

La importación de exportaciones predeterminadas es similar a la importación de exportaciones con nombre, excepto que puede usar cualquier nombre de su elección para importarlas.

busca el número que me llamó

Por ejemplo:

//otherModule.js 
const Bar = require("./main");
const object = new Bar();
object.bar();

En el bloque de código anterior, la exportación predeterminada se nombró Bar , aunque puede utilizar cualquier nombre de su elección.

El sistema de módulos ES6

El sistema de módulos ECMAScript Harmony, conocido popularmente como módulos ES6, es el sistema de módulos oficial de JavaScript.

Los módulos ES6 son compatibles con navegadores y servidores, aunque requiere un poco de configuración antes de usarlos.

En los navegadores, debe especificar el escribe como módulo en la etiqueta de importación del script.

Al igual que:

//index.html 
<script src="./app.js" type="module"></script>

En Node.js, debe configurar escribe a módulo en tus paquete.json expediente.

Al igual que:

//package.json 
"type":"module"

También puede exportar variables utilizando el sistema de módulos ES6 mediante exportaciones con nombre o exportaciones predeterminadas.

Exportaciones con nombre

Al igual que las importaciones con nombre en los módulos de CommonJS, se identifican por los nombres que se les asignaron y permiten múltiples exportaciones por módulo.

Por ejemplo:

//main.js 
export const myExport = function () {
console.log("This is an example of a named export");
};
export const anotherExport = function () {
console.log("This is another example of a named export");
};

En el sistema de módulos ES6, las exportaciones con nombre se exportan prefijando la variable con el exportar palabra clave.

Las exportaciones con nombre se pueden importar a otro módulo en ES6 de la misma manera que CommonJS:

  • La desestructuración de las exportaciones requeridas del exportaciones objeto.
  • Importando todas las exportaciones como un solo objeto y accediendo a ellas por separado usando la notación de puntos.

He aquí un ejemplo de desestructuración:

//otherModule.js 
import { myExport, anotherExport } from "./main.js";
myExport()
anotherExport()

Aquí hay un ejemplo de importar el objeto completo:

import * as foo from './main.js' 
foo.myExport()
foo.anotherExport()

En el bloque de código anterior, el asterisco ( * ) significa “todos”. los como palabra clave asigna la exportaciones objeto a la cadena que le sigue, en este caso, Foo .

Exportaciones predeterminadas

Al igual que las exportaciones predeterminadas en CommonJS, se identifican con cualquier nombre que elija y solo puede tener una exportación predeterminada por módulo.

Por ejemplo:

//main.js 
class Foo {
bar() {
console.log("This is an example of a default export");
}
}
export default Foo;

Las exportaciones predeterminadas se crean agregando el defecto palabra clave después de la exportar palabra clave, seguida del nombre de la exportación.

La importación de exportaciones predeterminadas es similar a la importación de exportaciones con nombre, excepto que puede usar cualquier nombre de su elección para importarlas.

Por ejemplo:

//otherModule.js 
import Bar from "./main.js";

Exportaciones Mixtas

El estándar del módulo ES6 le permite tener exportaciones predeterminadas y exportaciones con nombre en un módulo, a diferencia de CommonJS.

Por ejemplo:

//main.js 
export const myExport = function () {
console.log("This is another example of a named export");
};
class Foo {
bar() {
console.log("This is an example of a default export");
}
}
export default Foo;

Importancia de los módulos

Dividir su código en módulos no solo los hace más fáciles de leer, sino que también lo hace más reutilizable y fácil de mantener. Los módulos en JavaScript también hacen que su código sea menos propenso a errores, ya que todos los módulos se ejecutan en modo estricto de forma predeterminada.