Estructura de archivos

Estructura de carpetas y archivos de un proyecto

Ahora que ya conocemos las bases de los Custom Elements (la parte de WebComponents que permite crear nuestras propias etiquetas), toca comenzar a crear componentes básicos para ir viendo la estructura que podemos seguir para dotarle de funcionalidad. En este artículo vamos a ver como preparar una estructura de carpetas y archivos utilizando WebComponents, como crear nuestro primer componente y las diferentes formas de enlazarlo, tanto desde HTML como desde Javascript.

Estructura de componentes

Estructura de archivos

Quizás, lo primero que deberíamos tener claro es la estructura de carpetas y archivos que vamos a tener para crear nuestros componentes.

En principio, esta «arquitectura» depende mucho de lo que queramos hacer y es muy variable dependiendo de nuestros objetivos, pero vamos a partir de ejemplo sencillo de base, donde src es la carpeta que contiene nuestro código fuente:

- src
+-- components/
| +-- AppElement.js
+-- index.html
+-- index.js

Partimos de un archivo index.html (el punto de entrada, el fichero que abre inicialmente el navegador). Dicho archivo HTML puede cargar directamente (como veremos más adelante) el componente AppElement.js, que se encuentra dentro de la carpeta components/, o puede cargarlo a través de un fichero index.js que hace de fichero «centralizador».

Nuevamente, dejar claro que esto es sólo un ejemplo de partida y que esta estructura puede variar mucho dependiendo del proyecto, objetivo y necesidades. Aún así, es un buen ejemplo inicial para comenzar.

Crear un WebComponent

Para empezar, vamos a crear el componente básico mínimo necesario para hacerlo funcionar. Como ya hemos visto, esta formado de una clase que debe extender de HTMLElement, y asociarlo por medio de customElements.define() con el nombre de una etiqueta HTML (nuestro custom element):

class AppElement extends HTMLElement {

constructor() {
super();
}

}

customElements.define("app-element", AppElement);

Como buena práctica, este fichero suele nombrarse igual que la clase, AppElement.js y suele colocarse en una carpeta components/, aunque esto puede depender de la arquitectura utilizada.

Nota: En los casos que el constructor del componente no tenga ninguna lógica (solo incluya el super(), como en el ejemplo anterior) podemos ahorrarnos escribir el constructor, ya que es el comportamiento que tiene por defecto.

Cargar componentes

Como habrás observado, tenemos los archivos index.html e index.js, y la carpeta components/ que contiene el archivo AppElement.js. Sin embargo, no hemos mencionado como están cargados. Se puede hacer de varias formas, vamos a analizarlas:

Enlazar desde HTML (script)

Una vez tengamos un WebComponent creado, lo que toca es aprender los pasos para cargarlo y utilizarlo. Probablemente, la forma más fácil de hacerlo, es cargándolo desde el HTML de la siguiente forma:

  1. Cargamos el archivo Javascript del componente, usualmente desde el <head> del documento:
<script src="./components/AppElement.js"></script>
  1. Una vez hecho esto, usamos el componente (custom element) donde se requiera, simplemente con su etiqueta:
<app-element></app-element>

Como ven, rápido y sencillo. Sin complicaciones.

Enlazar desde Javascript

Sin embargo, podríamos preferir cargar el WebComponent desde Javascript en lugar de HTML, ya que puede ser más versátil y flexible en ciertas situaciones. Por ejemplo, si tenemos un gran número de componentes quizás podemos preferir centralizar los import en un fichero central de Javascript, que pueda ser reutilizado, en lugar de tener varias etiquetas <script> en varios archivos HTML diferentes.

En ese caso, debemos hacer lo siguiente:

  1. Cargamos un archivo Javascript donde vamos a centralizarlo todo. Este puede estar en el raíz o en una carpeta js/, dependiendo de nuestra arquitectura de carpetas. En cualquier caso, será el equivalente al «main» de muchos lenguajes de programación:
<script type="module" src="/js/index.js"></script>

Es muy importante darse cuenta de que es obligatorio utilizar el atributo type establecido a module. Con esto le indicamos al navegador que lo que estamos cargando es un fichero Javascript que va a importar módulos ES utilizando la sentencia import.

Si se nos olvidara añadir el type="module" a nuestro script, probablemente en la consola Javascript nos aparecerá un error similar al siguiente:

Uncaught SyntaxError: Cannot use import statement outside a module

  1. Por su parte, en el fichero index.js tendremos que hacer las importaciones necesarias para cargar el componente y poder utilizarlo posteriormente:
import "./components/AppElement.js";

Con esta modalidad de importación, simplemente indicamos a Javascript que incluya y procese el código que contiene dicho fichero Javascript, cargando el componente de una forma análoga a como lo hicimos en el apartado anterior, mediante HTML y una etiqueta <script>.

Enlazar desde HTML/Javascript

Hay una forma híbrida entre las dos anteriores, donde podemos hacer lo siguiente en nuestro archivo index.html:

<script type="module">
import "./components/AppElement.js";
</script>

Como ves, hemos incluido el contenido del fichero index.js en el interior de la etiqueta <script> del index.html. Aunque esta modalidad funciona, puede que no nos interese si tenemos múltiples ficheros .html, ya que en esta modalidad, los import quedan en el interior del fichero .html y es menos versátil que tenerlo separado en un archivo a parte.

Utilizar un componente

Una vez tengamos nuestro componente cargado y enlazado, existen varias formas de consumirlo (utilizarlo) en nuestra página. Veamos un resumen de cada una de ellas:

Crear etiqueta desde HTML

La primera y más sencilla ya la hemos visto, simplemente se trata de escribir el nombre de nuestra etiqueta HTML personalizado en el HTML:

<app-element></app-element>

Esta es la forma más básica y común. Sin embargo, no es la única.

Crear etiqueta desde Javascript

Puede interesarnos crear el componente desde Javascript, útil para hacerlo dinámico, usarlo en bucles, condicionales y/o aprovecharnos de toda la potencia de Javascript. En ese caso, tendríamos que hacer lo siguiente:

const appElement = document.createElement("app-element");
document.body.appendChild(appElement);

Hemos hecho lo siguiente:

  1. Creamos el elemento HTML <app-element> en memoria, en la variable appElement.
  2. Insertamos el elemento en el DOM del documento HTML, concretamente al final del <body>.

Existe una variación de la anterior. Para hacerlo de esta forma, en nuestro fichero AppElement.js, tendríamos que exportar la clase, para así poder importarla desde otro archivo. Haríamos la siguiente modificación:

export class AppElement extends HTMLElement {
/* ... */
}

Ahora, desde nuestro archivo index.js, en lugar de hacer una importación directa como la que vimos más atrás, la haríamos de esta forma, importando la clase AppElement para luego crear una instancia utilizando el new:

import { AppElement } from "./components/AppElement.js";

const appElement = new AppElement();
document.body.appendChild(appElement);

Obsérvese que en el fichero index.js hemos importado la clase AppElement que exportamos en el punto anterior. En el resto del código del fichero podríamos ahora trabajar con ella de forma análoga a como lo hicimos más atrás con .createElement().

Tabla de contenidos