Módulos JavaScript

Esta guía te brinda todo lo que necesitas para comenzar con la sintaxis de los módulos JavaScript.

Un antecedente sobre módulos

Los programas JavaScript comenzaron siendo bastante pequeños — la mayor parte de su uso en los primeros días era para realizar tareas de scripting aisladas, proporcionando un poco de interactividad a tus páginas web donde fuera necesario, por lo que generalmente no se necesitaban grandes scripts. Avancemos unos años y ahora tenemos aplicaciones completas que se ejecutan en navegadores con mucho JavaScript, JavaScript ahora se usa en otros contextos (Node.js, por ejemplo).

Por lo tanto, en los últimos años se ha comenzado a pensar en proporcionar mecanismos para dividir programas JavaScript en módulos separados que se puedan importar cuando sea necesario. Node.js ha tenido esta capacidad durante mucho tiempo, y hay una serie de bibliotecas y marcos de JavaScript que permiten el uso de módulos (por ejemplo, CommonJS y AMD otros basados en sistemas de módulos como RequireJS, y recientemente Webpack y Babel).

La buena noticia es que los navegadores modernos han comenzado a admitir la funcionalidad de los módulos de forma nativa, y de esto se trata este artículo. Esto solo puede ser algo bueno — los navegadores pueden optimizar la carga de módulos, haciéndolo más eficiente que tener que usar una biblioteca y hacer todo ese procesamiento adicional de lado del cliente, ahorrando viajes de ida y vuelta adicionales.

Compatibilidad con navegadores

Introducción — un ejemplo

Para demostrar el uso de módulos, hemos creado un sencillo conjunto de ejemplos que puedes encontrar en GitHub. Estos ejemplos demuestran un sencillo conjunto de módulos que crean un elemento en una página web, y luego dibujan (y reportan información sobre) diferentes formas en el lienzo.

Estos son bastante triviales, pero se han mantenido deliberadamente simples para demostrar los módulos con claridad.

Nota: Si deseas descargar los ejemplos y ejecutarlos localmente, deberás ejecutarlos a través de un servidor web local.

Estructura básica de los ejemplos

En nuestro primer ejemplo (ve basic-modules) tenemos la siguiente estructura de archivos:

index.html
main.js
modules/
    canvas.js
    square.js

Nota: Todos los ejemplos de esta guía básicamente tienen la misma estructura; lo anterior debería empezar a resultarte bastante familiar.

Los dos módulos del directorio modules se describen a continuación:

  • canvas.js — contiene funciones relacionadas con la configuración del lienzo (canvas):

    • create() — crea un lienzo (canvas) con un width y height especificados dentro de un contenedor
      con un ID especificado, que a su vez se añade dentro de un elemento padre especificado. Devuelve un objeto que contiene el contexto 2D del lienzo y el ID del contenedor.
    • createReportList() — crea una lista desordenada adjunta dentro de un elemento contenedor específico, que se puede usar para generar datos de informes. Devuelve el ID de la lista.
  • square.js — contiene:

    • name — una constante que contiene la cadena 'square'.
    • draw() — dibuja una figura cuadrada en un lienzo específico, con un tamaño, posición y color específicos. Devuelve un objeto que contiene el tamaño, la posición y el color del cuadrado.
    • reportArea() — escribe el área de un cuadrado en una lista de informes específica, dada su longitud.
    • reportPerimeter() — escribe el perímetro de un cuadrado en una lista de informes específica, dada su longitud.

Reflexión — .mjs versus .js

A través de este artículo, usaremos extensiones .js para nuestros archivos de módulo, pero en otros recursos, puedes ver que en su lugar se usa la extensión .mjs. La documentación de V8 recomienda esto, por ejemplo. Las razones dadas son:

  • Es bueno por claridad, es decir, deja claro qué archivos son módulos y cuáles JavaScript.
  • Asegura que tus archivos de módulo sean analizados como un módulo por los entornos de ejecución como Node.js y herramientas de compilación como Babel.

Sin embargo, decidimos seguir usando .js, al menos por el momento. Para que los módulos funcionen correctamente en un navegador, debes asegurarte de que tu servidor los esté sirviendo con un encabezado Content-Type que contenga un tipo MIME de JavaScript como text/javascript. Si no lo haces, obtendrás un estricto error de verificación de tipo MIME como "El servidor respondió con un tipo MIME que no es JavaScript" y el navegador no ejecutará tu JavaScript. La mayoría de los servidores ya configuran el tipo correcto para archivos .js, pero todavía no para archivos .mjs. Los servidores que ya sirven archivos .mjs incluyen GitHub Pages y http-server para Node.js.

Esto está bien si ya estás utilizando un entorno de este tipo, o si no, pero sabes lo que estás haciendo y tiene acceso (es decir, puedes configurar tu servidor para establecer el Content-Type para archivos .mjs). Sin embargo, podría causar confusión si no controlas el servidor desde el que estás sirviendo archivos, o si estás publicando archivos para uso público, como lo hacemos aquí.

Por motivos de aprendizaje y portabilidad, decidimos mantenernos en .js.

Si realmente valoras la claridad de usar .mjs para módulos en lugar de usar .js para archivos JavaScript "normales", pero no quieres encontrarte con el problema descrito anteriormente, siempre puedes usar .mjs durante el desarrollo y convertirlos a .js durante tu paso de compilación.

También vale la pena señalar que:

  • Es posible que algunas herramientas nunca admitan .mjs, tal como TypeScript.
  • El atributo

También puedes incrustar el script del módulo directamente en el archivo HTML colocando el código JavaScript dentro del cuerpo del elemento