Concepts de base
Cette section explique comment les éléments clés d’O3 s’articulent. À la fin, vous devriez comprendre comment O3 démarre et comment les modules sont chargés et configurés. Le schéma ci-dessous montre les principaux blocs et leurs liens.
Notes sur le schéma (pour la clarté) : spa-assemble-config.json sert pendant l’assemblage d’une distribution à
télécharger les packages de modules frontend et à produire les deux artefacts lus par l’app shell à l’exécution :
importmap.json et routes.registry.json. Les modules ne se chargent pas directement depuis npm à l’exécution. Ils se
chargent depuis les URLs de bundles dans la carte d’importation, ou depuis des URLs de serveur de dev local quand les
overrides de carte d’importation et de routes sont actifs.
Les principaux éléments de l’architecture frontale d’O3 sont les suivants :
- Le shell de l’application - la couche de base qui coordonne le démarrage et l’exécution.
- Les modules frontaux - blocs UI composables.
- La carte d’importation - un fichier JSON qui associe les noms de modules aux URLs de leurs bundles.
- Le registre des routes - un fichier JSON qui indique au shell quelles pages, extensions, modales, workspaces et feature flags les modules fournissent.
- Le core framework - bibliothèques et API partagées par les modules frontaux.
Où cela se trouve dans le code
Deux dépôts sont particulièrement utiles pour retrouver ces concepts dans le vrai code. Le monorepo
openmrs-esm-core contient le runtime et l’outillage :
- App shell :
packages/shell/esm-app-shell - Core framework (agrégé) :
packages/framework/esm-framework - Librairies du framework (packages individuels) :
packages/framework/* - Modules frontend de base :
packages/apps/* - Lecteurs de cartes et chargement dynamique :
packages/framework/esm-dynamic-loading - Enregistrement des routes et extensions :
packages/framework/esm-routes - Outillage d’assemblage des distributions :
packages/tooling/openmrs
Le dépôt openmrs-distro-referenceapplication montre
comment une vraie distribution utilise cet outillage. Son frontend/spa-assemble-config.json choisit les modules frontend
et leurs versions, tandis que frontend/spa-build-config.json indique à l’app shell générée où trouver la carte
d’importation et le registre des routes.
Shell de l’application
L’app shell est l’application hôte qui démarre O3 et coordonne le chargement et les services d’exécution. Introduit dans RFC-26 , il gère :
- Démarrage : rend
index.html, charge la carte d’importation et le registre des routes, puis connecte le chargement et le routage des modules. - Services d’exécution : définit points d’arrêt, abonnements (modales, toasts, notifications) et le mode hors ligne.
- Couplage plateforme : initialise l’état global et met en place configuration et extensions.
Au démarrage, l’app shell n’exécute pas immédiatement tous les modules frontend. Il met en place les services UI de base,
lit les balises <script type="systemjs-importmap"> et <script type="openmrs-routes"> dans index.html, enregistre les
métadonnées déclarées dans le registre des routes, charge la configuration, puis démarre single-spa. Le code d’un module
est récupéré plus tard, lorsqu’une route, une extension, une modale ou un workspace a réellement besoin d’une fonction de
cycle de vie exportée par ce module.
Pour aller plus loin : Approfondir la coque d’application
Modules frontaux
Les modules frontaux sont les unités de fonctionnalité qui composent l’UI d’O3. Pensez à chaque module comme une mini‑application qui gère une partie de l’interface (par exemple, le dossier patient ou la navigation principale).
O3 traite ces modules comme des microfrontends (terme popularisé par single-spa ).
L’app shell lit le registre des routes généré depuis les métadonnées de routes de chaque module sélectionné, enregistre les
pages, extensions, modales, workspaces et feature flags déclarés, puis charge les fonctions de cycle de vie exportées par
le module depuis la carte d’importation quand du code UI est nécessaire. Si un module exporte startupApp(), l’app shell
l’appelle une fois avant de charger les fonctions de cycle de vie de ce module. Les modules exportent des fonctions de
cycle de vie adaptées à single-spa, conformes à
l’interface définie dans RFC-26 .
Dans la plupart des distributions, la carte d’importation et le registre des routes sont générés pendant l’assemblage de
la distribution à partir de spa-assemble-config.json et des métadonnées de routes des modules sélectionnés.
Les extensions sont des blocs UI plug‑in que les modules définissent pour des emplacements nommés.
Notions essentielles (les fichiers que vous manipulerez le plus souvent) :
package.json- métadonnées, scripts et dépendances du modulesrc/index.ts- point d’entrée qui exporte fonctions de cycle de vie et code de démarragesrc/routes.json- métadonnées statiques pour l’app shellsrc/config-schema.ts- où se trouvent les propriétés de configuration du module
Le code des modules frontaux est chargé à la demande par l’app shell lorsqu’il est nécessaire, ce qui améliore le temps de chargement initial.
Les modules frontaux peuvent vivre dans des dépôts autonomes ou dans des monorepos orientés domaine lorsque plusieurs
modules partagent un même périmètre. Par exemple, les modules de gestion des patients (inscription, files d’attente,
rendez-vous, gestion des lits, etc.) sont regroupés dans le monorepo
openmrs-esm-patient-management.
Vous choisissez quels modules inclure dans une distribution en modifiant son fichier spa-assemble-config.json. Pour
ajouter un module personnalisé, générez-le avec npm create @openmrs/o3-app@latest, publiez-le sur npm sous votre propre
espace de noms, puis ajoutez une entrée pour ce module dans spa-assemble-config.json. Le dépôt
template app reste utile comme référence pour la structure de module
générée.
Ensuite :
Carte d’importation
Une carte d’importation est une spécification du navigateur qui mappe des noms de modules vers leurs URLs de chargement. Introduite dans RFC-4 , elle indique au shell où récupérer chaque module. L’app shell précharge la carte au démarrage puis l’utilise pour résoudre et charger les bundles.
En pratique, les cartes d’importation sont générées et servies par la distribution (pas par l’app shell). Par exemple,
la carte d’importation de l’application de référence de la communauté O3 est
servie à /openmrs/spa/importmap.json, et la liste de modules et de versions qui la génère se trouve dans
frontend/spa-assemble-config.json.
La plupart des distributions suivent la même approche.
Pour voir la carte d’importation de votre distro dans le navigateur, naviguez vers /openmrs/spa/importmap.json (ou le
chemin de base SPA de votre distro), où vous verrez un extrait simplifié comme:
{
"imports": {
"@openmrs/esm-home-app": "./openmrs-esm-home-app-4.1.1-pre.211/openmrs-esm-home-app.js",
"@openmrs/esm-login-app": "./openmrs-esm-login-app-4.3.2-pre.671/openmrs-esm-login-app.js",
"@openmrs/esm-primary-navigation-app": "./openmrs-esm-primary-navigation-app-4.3.2-pre.671/openmrs-esm-primary-navigation-app.js",
"@openmrs/esm-patient-chart-app": "./openmrs-esm-patient-chart-app-4.3.1-pre.1352/openmrs-esm-patient-chart-app.js"
}
}Les clés de cet objet sont les noms des modules (identifiants uniques) et les valeurs sont des URLs de bundles. Ces URLs
sont souvent des chemins relatifs dans les distributions assemblées, mais les overrides de développement local peuvent
pointer vers des URLs absolues, par exemple un serveur de dev local. Le shell lit la carte d’importation à l’exécution
lorsqu’il doit charger le code d’un module. Les modules frontend O3 actuels sont chargés comme des conteneurs Module
Federation : l’app shell ajoute une balise script pour l’URL du bundle, puis appelle les méthodes init et get du
conteneur pour charger les fonctions de cycle de vie exportées. Voir la page Approfondir la coque d’application
pour les détails du chargement.
Pour aller plus loin : Chargement des modules
Registre des routes
Le registre des routes est un objet JSON qui associe les noms de modules aux métadonnées statiques provenant des fichiers
routes.json de ces modules. L’app shell le lit au démarrage pour enregistrer :
- Les pages et leurs routes
- Les extensions et les slots auxquels elles s’attachent
- Les modales, workspaces, groupes de workspaces et feature flags
Pendant l’assemblage d’une distribution, openmrs assemble extrait chaque module frontend sélectionné, lit son
routes.json packagé, puis écrit le registre combiné dans routes.registry.json. En développement local,
openmrs develop lit directement src/routes.json et sert un registre généré pour l’application en cours de développement.
C’est volontairement séparé de la carte d’importation. La carte d’importation répond à « où se trouve le bundle JavaScript de ce module ? » Le registre des routes répond à « quelles pages, extensions et autres points d’entrée UI ce module fournit-il ? » Un module a généralement besoin d’entrées aux deux endroits avant que son UI puisse s’afficher.
Comment O3 charge les modules (modèle mental rapide)
- L’app shell démarre et précharge la carte d’importation et le registre des routes.
- Il lit le registre des routes et enregistre les pages, extensions, modales, workspaces et feature flags déclarés.
- Quand une route, une extension, une modale ou un workspace a besoin de code, il résout l’URL du module dans la carte d’importation et charge ses fonctions de cycle de vie exportées.
- Le routeur monte les pages au fil de la navigation, et les slots d’extension montent les extensions lorsque leur UI hôte s’affiche.
Si vous devez changer…
- Quels modules et versions sont inclus dans une distribution → modifiez
spa-assemble-config.json. - Quelles pages ou extensions un module fournit → modifiez le fichier
src/routes.jsondu module. - Comment les modules se chargent globalement → comportement de l’app shell et du chargement dynamique.
- Ce que fait un module après son chargement → dépôt du module (UI, exports de cycle de vie, config et logique métier).
Cadre de base
Le framework O3 est la bibliothèque runtime partagée sur laquelle les modules frontend s’appuient. Il est publié sous
@openmrs/esm-framework, mais dans le dépôt source il est composé
de plusieurs packages ciblés sous packages/framework/*. Le package agrégé réexporte les API publiques de ces packages,
ce qui permet aux modules d’importer le plus souvent depuis un seul endroit :
import { openmrsFetch, useConfig, ExtensionSlot, showToast } from "@openmrs/esm-framework";Pensez au framework comme au contrat entre l’app shell et les modules frontend. L’app shell décide quels modules sont disponibles et quand leur code doit se charger. Le framework fournit les API que ces modules utilisent après leur chargement.
Les éléments les plus importants sont :
- API backend et session :
openmrsFetch, URLs de base REST, vérification des dépendances backend, helpers de session et d’utilisateur courant, utilitaires patient/visite et abonnements aux événements. - Systèmes de métadonnées runtime : schémas de configuration, enregistrement des extensions, slots d’extension, feature flags, stores globaux, contexte d’application et évaluation d’expressions.
- Helpers de rendu et de cycle de vie : hooks React, composants
ExtensionetExtensionSlot, helpers de cycle de vie commegetSyncLifecycleetgetAsyncLifecycle, et utilitaires qui adaptent les composants React aux cycles de vie single-spa. - Services UX partagés : composants du styleguide, navigation et fil d’Ariane, modales, workspaces, toasts, snackbars, notifications, traductions et prise en charge du mode hors ligne.
Pour les auteurs de modules, la règle pratique est d’utiliser le framework pour les comportements transversaux d’O3 au
lieu d’inventer localement des wrappers de fetch, de l’état global, du câblage d’extensions, du chargement de configuration
ou une UI de notification. Si vous devez modifier le comportement global de ces systèmes partagés, ce changement appartient
généralement à openmrs-esm-core, pas à un module frontend individuel.
Pour aller plus loin : Référence de l’API du framework
Prochaines étapes
Prêt à construire ? Continuez avec Modules frontend pour voir comment les modules sont structurés et chargés.