preloader

Introduccion a los modulos en JavaScript

Introduccion a los modulos en JavaScript

A medida que nuestras aplicaciones crecen, queremos dividirlas en múltiples archivos, conocidos como “módulos”. Un módulo puede contener una clase o una biblioteca de funciones destinadas a un propósito específico.

Durante mucho tiempo, JavaScript no tuvo una sintaxis de módulos a nivel de lenguaje. Esto no era un problema inicialmente, ya que los scripts eran pequeños y simples.

Sin embargo, a medida que los scripts se volvieron más complejos, la comunidad desarrolló diversas formas de organizar el código en módulos, utilizando bibliotecas especiales para cargar módulos según sea necesario.

Algunos de estos métodos históricos incluyen:

  • AMD (Asynchronous Module Definition): uno de los primeros sistemas de módulos, implementado inicialmente por la biblioteca require.js.
  • CommonJS: un sistema de módulos creado para el entorno de servidor Node.js.
  • UMD (Universal Module Definition): un sistema de módulos diseñado para ser compatible tanto con AMD como con CommonJS.

Aunque estos sistemas se utilizan menos hoy en día, todavía se pueden encontrar en scripts antiguos.

En 2015, se introdujo en el estándar un sistema de módulos a nivel de lenguaje, que ha evolucionado gradualmente y ahora es compatible con todos los navegadores principales y Node.js. En adelante, estudiaremos los módulos modernos de JavaScript.

¿Qué es un módulo?

Un módulo es simplemente un archivo. Un script es un módulo. Tan sencillo como eso.

Los módulos pueden cargarse entre sí y usar las directivas especiales export e import para compartir funcionalidades, permitiendo llamar a funciones de un módulo desde otro.

  • La palabra clave export marca las variables y funciones que deben ser accesibles desde fuera del módulo actual.
  • import permite importar funcionalidades de otros módulos.

Por ejemplo, si tenemos un archivo sayHi.js que exporta una función:

				
					// 📁 sayHi.js
export function sayHi(user) {
  alert(`Hello, ${user}!`);
}

				
			

Otro archivo puede importarlo y usarlo:

				
					// 📁 main.js
import {sayHi} from './sayHi.js';

alert(sayHi); // function...
sayHi('John'); // Hello, John!

				
			

La directiva import carga el módulo desde la ruta ./sayHi.js, relativa al archivo actual, y asigna la función exportada sayHi a la variable correspondiente.

Para que el navegador trate un script como un módulo, debemos usar el atributo <script type="module">.

Por ejemplo:

				
					<!doctype html>
<script type="module">
  import {sayHi} from './sayHi.js';

  document.body.innerHTML = sayHi('John');
</script>

				
			

El navegador buscará y evaluará automáticamente el módulo importado (y sus importaciones si es necesario), y luego ejecutará el script.

Características principales de los módulos

Los módulos difieren de los scripts “normales” en varios aspectos:

  1. Modo estricto por defecto: Los módulos siempre operan en modo estricto. Por ejemplo, asignar una variable sin declararla resultará en un error.

				
					<script type="module">
  a = 5; // error
</script>

				
			

Ámbito a nivel de módulo: Cada módulo tiene su propio ámbito de nivel superior. Las variables y funciones de nivel superior de un módulo no son visibles para otros scripts.

				
					// user.js
export let user = "John";

// hello.js
import {user} from './user.js';

document.body.innerHTML = user; // John

				
			

Evaluación única: El código de un módulo se evalúa solo la primera vez que se importa. Las exportaciones se comparten entre todos los importadores subsecuentes.

				
					// admin.js
export let admin = {
  name: "John"
};

// 1.js
import {admin} from './admin.js';
admin.name = "Pete";

// 2.js
import {admin} from './admin.js';
alert(admin.name); // Pete

				
			

import.meta: El objeto import.meta contiene información sobre el módulo actual, como la URL del script en el navegador.

				
					<script type="module">
  alert(import.meta.url); // URL del script
</script>

				
			

this en módulos: En un módulo, this es undefined en el nivel superior.

				
					<script>
  alert(this); // window
</script>

<script type="module">
  alert(this); // undefined
</script>

				
			

Funciones específicas del navegador

Los módulos tienen algunas características específicas en el navegador:

  • Los módulos son diferidos: Los módulos se cargan en paralelo junto con otros recursos y se ejecutan una vez que el documento HTML está completamente cargado.
				
					<script type="module">
  alert(typeof button); // object
</script>

<script>
  alert(typeof button); // undefined
</script>

<button id="button">Button</button>

				
			

Scripts externos duplicados: Los scripts externos con el mismo src solo se ejecutan una vez.

				
					<script type="module" src="my.js"></script>
<script type="module" src="my.js"></script>

				
			

Compatibilidad con navegadores antiguos: Los navegadores antiguos no entienden type="module". Podemos proporcionar una alternativa usando nomodule.

				
					<script type="module">
  alert("Se ejecuta en navegadores modernos");
</script>

<script nomodule>
  alert("Se ejecuta en navegadores antiguos");
</script>

				
			

Herramientas de empaquetado

En la práctica, los módulos de navegador rara vez se utilizan en su forma pura. Generalmente, se agrupan con herramientas como Webpack para mejor rendimiento y otras razones.

Estas herramientas:

  • Toman un módulo principal y analizan sus dependencias.
  • Compilan un archivo único con todos los módulos.
  • Aplican transformaciones y optimizaciones, como la eliminación de código no utilizado.
  • Minimizan el archivo resultante.

Por ejemplo, el script empaquetado resultante no contiene import/export y se puede colocar en un script normal:

				
					<script src="bundle.js"></script>

				
			

Resumen

Para resumir, los conceptos clave son:

  • Un módulo es un archivo. Para que import/export funcione, los navegadores necesitan <script type="module">.
  • Los módulos tienen varias diferencias con los scripts normales, como el modo estricto por defecto y un ámbito de nivel superior independiente.
  • El código del módulo se ejecuta solo una vez y las exportaciones se comparten entre importadores.
  • En la producción, se suelen usar herramientas de empaquetado como Webpack para agrupar módulos y optimizar el rendimiento.

En el próximo capítulo, veremos más ejemplos de módulos y cómo exportar e importar diversas funcionalidades.

Related Post

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *