Aplicar los principios de programación de miniapps a un proyecto de ejemplo

El dominio de la app

Para mostrar la forma de programar miniapps aplicada a una aplicación web, necesitaba una idea de app pequeña pero completa. Entrenamiento de intervalos de alta intensidad (HIIT) es una estrategia de ejercicio cardiovascular que consiste en alternar series breves de ejercicios anaeróbicos intensos con períodos de recuperación menos intensos. Muchos entrenamientos de HIIT usan cronómetros de HIIT, por ejemplo, esta sesión en línea de 30 minutos. del canal de YouTube The Body Coach TV.

Sesión en línea de entrenamiento HIIT con temporizador verde de alta intensidad.
Período activo.
Sesión en línea de entrenamiento HIIT con temporizador rojo de baja intensidad.
. Período de descanso

App de ejemplo de hora HIIT

Para este capítulo, creé un ejemplo básico de una aplicación de temporizador HIIT llamada acertadamente. “Hora de HIIT” que permite al usuario definir y administrar varios temporizadores siempre consiste en un intervalo de intensidad alta y otra baja, y, luego, seleccionar uno de ellos para una sesión de capacitación. Es una app responsiva con una barra de navegación, una barra de pestañas y tres páginas:

  • Entrenamiento: Es la página activa durante un entrenamiento. Permite al usuario seleccionar uno de los cronómetros y presenta tres anillos de progreso: el número de series, el período activo y el período de descanso.
  • Temporizadores: Administra los cronómetros existentes y permite al usuario crear temporizadores nuevos.
  • Preferences: Permite activar o desactivar los efectos de sonido y la salida de voz, así como seleccionar el idioma y el tema.

Las siguientes capturas de pantalla muestran una impresión de la aplicación.

App de ejemplo de hora de HIIT en modo vertical.
Entrenamiento con HIIT Time en modo Retrato.
App de ejemplo de hora de HIIT en modo horizontal.
. Entrenamiento con HIIT Time en modo horizontal.
App de ejemplo de HIIT Time en la que se muestra la administración de un cronómetro.
. Administración del temporizador HIIT Time

Estructura de app

Como se describió anteriormente, la app consta de una barra de navegación, una barra de pestañas y tres páginas dispuestas en una cuadrícula. La barra de navegación y la barra de pestañas se crean como iframes con un contenedor <div> entre ellos con tres iframes más. para las páginas, de las cuales siempre estará visible una y que depende de la selección activa en la barra de pestañas. Se publica un iframe final que apunta a about:blank para las páginas integradas en la app creadas de forma dinámica, que son necesarias para modificar las existentes. temporizadores o crear temporizadores nuevos. A este patrón lo llamo aplicación de una sola página de varias páginas (MPSPA).

Vista de las Herramientas para desarrolladores de Chrome de la estructura HTML de la app que muestra que consta de seis iframes: uno para la barra de navegación, uno para la barra de pestañas y tres agrupados para cada página de la app, con un iframe de marcador de posición final para las páginas dinámicas.
La app consta de seis iframes.

Lenguaje de marcado lit-html basado en componentes

La estructura de cada página se realiza como un andamiaje lit-html. que se evalúa de forma dinámica durante el tiempo de ejecución. Para obtener información sobre lit-html, se trata de una biblioteca de plantillas HTML eficiente, expresiva y extensible para JavaScript. Si se usa directamente en los archivos HTML, el modelo de programación mental está orientado directamente al resultado. Como programador, escribes una plantilla de cómo se verá el resultado final, y lit-html luego llena los espacios vacíos dinámicamente según tus datos y conecta los objetos de escucha de eventos. La app usa elementos personalizados de terceros, como <sl-progress-ring> de Shoelace, o un elemento personalizado de implementación propia llamado <human-duration>. Dado que los elementos personalizados tienen una API declarativa (por ejemplo, el atributo percentage del anillo de progreso), funcionan bien con lit-html, como se puede observar en la siguiente lista.

<div>
  <button class="start" @click="${eventHandlers.start}" type="button">
    ${strings.START}
  </button>
  <button class="pause" @click="${eventHandlers.pause}" type="button">
    ${strings.PAUSE}
  </button>
  <button class="reset" @click="${eventHandlers.reset}" type="button">
    ${strings.RESET}
  </button>
</div>

<div class="progress-rings">
  <sl-progress-ring
    class="sets"
    percentage="${Math.floor(data.sets/data.activeTimer.sets*100)}"
  >
    <div class="progress-ring-caption">
      <span>${strings.SETS}</span>
      <span>${data.sets}</span>
    </div>
  </sl-progress-ring>
</div>
Tres botones y una rueda de progreso.
Sección renderizada de la página correspondiente al lenguaje de marcado anterior.

Modelo de programación

Cada página tiene una clase Page correspondiente que completa el lenguaje de marcado lit-html con vida mediante implementaciones de los controladores de eventos y proporcionar los datos de cada página. Esta clase también admite métodos de ciclo de vida, como onShow(), onHide(), onLoad() y onUnload(). Las páginas tienen acceso a un almacén de datos que sirve para compartir el estado global y el estado por página persistente opcionalmente. Todas las cadenas se administran de manera central, por lo que la internacionalización está integrada. El navegador controla el enrutamiento esencialmente gratis, ya que lo único que hace la aplicación es activar o desactivar la visibilidad del iframe y En el caso de las páginas creadas de forma dinámica, cambia el atributo src del iframe del marcador de posición. En el siguiente ejemplo, se muestra el código para cerrar una página creada de forma dinámica.

import Page from '../page.js';

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
La página en la app creada como un iframe.
La navegación se hace de iframe a iframe.

Diseño

El estilo de las páginas se realiza por página en su propio archivo CSS con alcance. Esto significa que los elementos pueden llegarse directamente con sus nombres ya que no pueden producirse conflictos con otras páginas. Los estilos globales se agregan a cada página, de modo que los parámetros de configuración centrales, como font-family o box-sizing, no es necesario declararlas repetidamente. Aquí también se definen los temas y las opciones del modo oscuro. En la siguiente lista, se muestran las reglas de la página Preferencias que detalla los distintos elementos del formulario en una cuadrícula.

main {
  max-width: 600px;
}

form {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-gap: 0.5rem;
  margin-block-end: 1rem;
}

label {
  text-align: end;
  grid-column: 1 / 2;
}

input,
select {
  grid-column: 2 / 3;
}
Página de preferencias de la app de HIIT Time en la que se muestra un formulario en diseño de cuadrícula.
Cada página tiene su propio mundo. El diseño se produce directamente con los nombres de los elementos.

Bloqueo de activación de pantalla

Durante el entrenamiento, la pantalla no debe apagarse. En los navegadores compatibles, HIIT Time lo detecta mediante un bloqueo de activación de pantalla. El siguiente fragmento muestra cómo se hace.

if ('wakeLock' in navigator) {
  const requestWakeLock = async () => {
    try {
      page.shared.wakeLock = await navigator.wakeLock.request('screen');
      page.shared.wakeLock.addEventListener('release', () => {
        // Nothing.
      });
    } catch (err) {
      console.error(`${err.name}, ${err.message}`);
    }
  };
  // Request a screen wake lock…
  await requestWakeLock();
  // …and re-request it when the page becomes visible.
  document.addEventListener('visibilitychange', async () => {
    if (
      page.shared.wakeLock !== null &&
      document.visibilityState === 'visible'
    ) {
      await requestWakeLock();
    }
  });
}

Prueba la aplicación

La aplicación de HIIT Time está disponible en GitHub. Puedes jugar con la demostración en una ventana nueva. o directamente en el iframe incorporado a continuación, que simula un dispositivo móvil.

Agradecimientos

Este artículo fue revisado por Joe Medley: Kayce Basques, Milica Mihajlija Alan Kent, y Keith Gu.