Appliquer les principes de programmation des mini-applications à un exemple de projet

Le domaine de l'application

Pour illustrer l'application de la programmation de mini-applications à une application Web, j'avais besoin d'une idée d'application petite, mais suffisamment complète. L'entraînement fractionné de haute intensité (HIIT) est une stratégie d'exercice cardiovasculaire qui consiste à alterner des séries de courtes périodes d'exercice anaérobie intense avec des périodes de récupération moins intenses. De nombreux entraînements HIIT utilisent des minuteurs HIIT, par exemple cette séance en ligne de 30 minutes sur la chaîne YouTube The Body Coach TV.

Séance d'entraînement HIIT en ligne avec un minuteur vert haute intensité.
Période d'activité.
Séance d'entraînement HIIT en ligne avec un minuteur rouge à faible intensité.
Période de repos.

Exemple d'application HIIT Time

Pour ce chapitre, j'ai créé un exemple de base d'une application de minuteur HIIT appelée "HIIT Time". Elle permet à l'utilisateur de définir et de gérer différents minuteurs, toujours composés d'un intervalle de haute intensité et d'un intervalle de faible intensité, puis d'en sélectionner un pour une séance d'entraînement. Il s'agit d'une application responsive avec une barre de navigation, une barre d'onglets et trois pages :

  • Workout (Entraînement) : page active pendant un entraînement. Elle permet à l'utilisateur de sélectionner l'un des minuteurs et comporte trois anneaux de progression : le nombre de séries, la période d'activité et la période de repos.
  • Timers (Minuteurs) : gère les minuteurs existants et permet à l'utilisateur d'en créer de nouveaux.
  • Preferences (Préférences) : permet d'activer ou de désactiver les effets sonores et la sortie vocale, et de sélectionner la langue et le thème.

Les captures d'écran suivantes donnent une idée de l'application.

Exemple d'application HIIT Time en mode Portrait.
Onglet "Workout" (Entraînement) de HIIT Time en mode portrait.
Exemple d'application HIIT Time en mode Paysage.
Onglet "Workout" (Entraînement) de HIIT Time en mode paysage.
Exemple d'application HIIT Time montrant la gestion d'un minuteur.
Gestion des minuteurs HIIT Time.

Structure de l'application

Comme indiqué ci-dessus, l'application se compose d'une barre de navigation, d'une barre d'onglets et de trois pages, disposées dans une grille. La barre de navigation et la barre d'onglets sont réalisées comme des iframes avec un conteneur <div> entre elles, ainsi que trois autres iframes pour les pages. L'une d'elles est toujours visible et dépend de la sélection active dans la barre d'onglets. Une dernière iframe pointant vers about:blank sert aux pages intégrées créées de manière dynamique, qui sont nécessaires pour modifier des minuteurs existants ou en créer de nouveaux. J'appelle ce modèle une application monopage multipage (MPSPA).

Vue Outils pour les développeurs Chrome de la structure HTML de l&#39;application montrant qu&#39;elle se compose de six iframes : un pour la barre de navigation, un pour la barre d&#39;onglets et trois regroupés pour chaque page de l&#39;application, avec un iframe d&#39;espace réservé final pour les pages dynamiques.
L'application se compose de six iframes.

Balisage lit-html basé sur des composants

La structure de chaque page est réalisée sous forme d'échafaudage lit-html qui est évalué de manière dynamique au moment de l'exécution. Pour en savoir plus sur lit-html, il s'agit d'une bibliothèque de modèles HTML efficace, expressive et extensible pour JavaScript. En l'utilisant directement dans les fichiers HTML, le modèle de programmation mentale est directement orienté vers la sortie. En tant que programmeur, vous écrivez un modèle de ce à quoi ressemblera la sortie finale, puis lit-html remplit les espaces vides de manière dynamique en fonction de vos données et connecte les écouteurs d'événements. L'application utilise des éléments personnalisés tiers tels que Shoelace's <sl-progress-ring> ou un élément personnalisé auto-implémenté appelé <human-duration>. Étant donné que les éléments personnalisés disposent d'une API déclarative (par exemple, l'attribut percentage de l'anneau de progression), ils fonctionnent bien avec lit-html, comme vous pouvez le voir dans la liste ci-dessous.

<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>
Trois boutons et un anneau de progression.
Section rendue de la page correspondant au balisage ci-dessus.

Modèle de programmation

Chaque page possède une classe Page correspondante qui remplit le balisage lit-html en fournissant des implémentations des gestionnaires d'événements et les données de chaque page. Cette classe est également compatible avec les méthodes de cycle de vie telles que onShow(), onHide(), onLoad() et onUnload(). Les pages ont accès à un datastore qui sert à partager l'état par page et l'état global éventuellement persistants. Toutes les chaînes sont gérées de manière centralisée, ce qui permet d'intégrer l'internationalisation. Le routage est géré par le navigateur de manière essentiellement sans frais, car tout ce que fait l'application, c'est activer ou désactiver la visibilité de l'iframe et, pour les pages créées de manière dynamique, modifier l'attribut src de l'iframe de l'espace réservé. L'exemple ci-dessous montre le code permettant de fermer une page créée de manière dynamique.

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

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
Page intégrée à l&#39;application réalisée sous forme d&#39;iFrame.
La navigation s'effectue d'une iframe à l'autre.

Attribution d'un style

Le style des pages est appliqué par page dans son propre fichier CSS délimité. Cela signifie que les éléments peuvent généralement être adressés directement par leur nom d'élément, car aucun conflit avec d'autres pages ne peut se produire. Les styles globaux sont ajoutés à chaque page. Par conséquent, les paramètres centraux tels que font-family ou box-sizing n'ont pas besoin d'être déclarés à plusieurs reprises. C'est également là que sont définis les thèmes et les options du mode sombre. La liste ci-dessous présente les règles de la page "Preferences" (Préférences) qui présente les différents éléments de formulaire dans une grille.

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;
}
Page des préférences de l&#39;application HIIT Time affichant un formulaire dans une disposition en grille.
Chaque page est son propre monde. Le style est appliqué directement avec les noms des éléments.

Wakelock forçant l'activation de l'écran

Pendant un entraînement, l'écran ne doit pas s'éteindre. Sur les navigateurs compatibles, HIIT Time y parvient grâce à un wakelock forçant l'activation de l'écran. L'extrait ci-dessous montre comment procéder.

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();
    }
  });
}

Tester l'application

L'application HIIT Time est disponible sur GitHub. Vous pouvez essayer la démo dans une nouvelle fenêtre, ou directement dans l'iframe intégrée ci-dessous, qui simule un appareil mobile.

Remerciements

Cet article a été examiné par Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent, et Keith Gu.