👉 Ver todas las notas
- Los módulos nos permiten exportar e importar diferentes partes de código, entre diferentes archivos, lo cual nos permite modularizar el código
- Un módulo no es más que un archivo (en este caso JS) que importamos/exportamos desde o hacia otro archivo para utilizarlo
- Definición cheta: un módulo es una unidad independiente (autocontenida) de código reutilizable, que podemos exportar para luego importarla y utilizarla en otro archivo (ó módulo)
- Otra: los módulos nos permiten encapsular funcionalidad y exponerla a otros archivos JS, como si se tratase de librerías (biliotecas)
- Para organizar mejor nuestro código.
- Igual, si, código más organizado => código más legible, simple, conciso, más fácil de razonar => más mantenible ✨
- Duplicación de código
- Namespacing (evitar la colisión de nombres de variables, funciones, clases, etc)
- Dependency Tree (cargar las dependencias necesarias, en el orden correcto)
- etc
- Cargábamos los diferentes
script
tags a mano en el HTML- Si los cargábamos en orden incorrecto (según las dependencias), no funcionaba
- Genera problemas de performance/usabilidad: hasta que no se termina de cargar un
script
, no se carga el siguiente y así, porque es render-blocking - tl;dr Hacer esto a mano es bastante molesto, perdemos mucho tiempo y casi siempre sale mal (la palabra técnica para eso es error-prone 😁)
- Antes de ES6 Modules, No teníamos una forma nativa (y standard) de cómo usar módulos en JS
- Más tarde fueron apareciendo diferentes soluciones de terceros (CommonJS, AMD, UMD, Browserify, etc) y era medio un complejo por temas de compatibilidad, etc
- Aparecen los package bundlers/module loaders que nos simplifican un poco la vida y hacen el trabajo sucio por nosotros, pero agregamos más herramientas y capas de complejidad a nuestro código
- Llamamos dependencias a la funcionalidad/valores que importamos en un archivo. Cuando un módulo importa funcionalidad de otro módulo, decimos que depende o tiene como dependencia a ese otro módulo
- Llamamos interfaz a la funcionalidad/valores que un módulo provee (exporta) al resto. Un módulo sólo puede importar funcionalidad que forme parte de la interfaz de otor módulo. Todo lo que no se exporta es privado dentro de un módulo y no puede ser usado fuera del mismo
- variables/constantes
- objetos
- funciones
- clases
Recíen a mediados del 2018 esta feature comenzó a tener más soporte, por lo que en algunos browsers posiblemente tengamos que usar herramientas (aka package bundlers) como Webpack o Parcel, para compilar nuestros módulos de ES6 a una sintaxis que el browser entienda.
- Named export: Lo usamos cuando queremos indicar explícitamente qué exportamos y con qué nombre. Permite exportar múltiples valores por archivo. Necesitamos usar
{}
en elimport
y llamarlo con el mismo nombre con el que fue exportado (ó usar un alias). Si el nombre no matchea con ningúnexport
, va a importar eldefault
export const package = {};
import { package } from './module-name.js';
// Podemos exportar múltiples valores
const a = 1;
const b = 2;
const c = 3;
export { a, b, c };
// Y después importar sólo los que vamos a usar (con destructuring!)
import { a, b } from './module-name.js'
// En el caso de ser necesario, podemos renombrar los imports, suando 'as'
import { a as one } from './module-name.js'
- Default export: Lo usamos generalmente cuando exportamos un único valor. Sólo puede haber un default export por módulo. No necesitamos usar
{}
en elimport
y podemos ponerle el nombre que querramos
export default const package = {};
import package from './module-name.js';
-
✨ Nota: podemos usar named y default exports en el mismo módulo
-
Wildcard export: Lo usamos si queremos importar todo lo que otro módulo exporta
const a = 1;
const b = 2;
const c = 3;
export { a, b, c };
// Importamos a, b y c
import * from './module-name.js'
// Exportar todos los _named export_ a un objeto
import * as MainComponents from "./MyComponent";
// Usamos MainComponents.MyComponent y MainComponents.MyComponent2 por ejemplo
- Absolute path: También podemos usar paths absolutos para referenciar módulos que se encuentran en otro dominio
import toUpperCase from 'https://git.io/fjjGt'
- Tenemos que agregar el atributo
type="module"
a nuestros tagsscript
para que el browser los cargue como ES6 Modules - Ojo con el tema de CORS, necesitamos levantar los archivos en un server. Algunas opciones: Live Server, http-server
- Para browsers sin soporte, podemos definir un
script
con al atributonomodule
como fallback
<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>
- Node utiliza CommonJS como sistema de módulos desde hace mucho tiempo
const package = require('module-name');
- Gracias a esta feature de ES6, podemos estandarizar y unificar la forma de usarlos. En la versión 12, el soporte para ES6 modules mejoró mucho
- Poner los imports siempre al inicio del archivo JS
- Si el archivo exporta una sola cosa, usar
export default
- Los Named imports llevan
{}
, los default no - Si el path no es absoluto, no olvidarnos de usar
./
o/
antes del nombre del módulo - No olvidarnos de ponerle la extensión
.js
al módulo que importamos
// Esto no funciona ❌
import { something } from './moduleName';
// Esto si ✅
import { something } from './moduleName.js';