Skip to Content

Performance

  • Utilisez judicieusement les hooks d’optimisation de performance intégrés de React :

    • useMemo pour les calculs coûteux.
    • useCallback pour les références de fonction stables.
    • memo pour empêcher les re-rendus inutiles de composants complexes.
    // Bon - mémorisation d'un calcul coûteux const sortedItems = useMemo(() => { return items .slice() .sort((a, b) => b.timestamp - a.timestamp); }, [items]); // Bon - callback stable pour les composants enfants const handleSubmit = useCallback((data: FormData) => { mutate(data); }, [mutate]);
  • Utilisez l’optimisation d’élément  pour éviter les re-rendus inutiles. Si vous donnez à React la même référence d’élément, il ignorera le rendu du composant.

  • Utilisez la méthode d’enregistrement de cycle de vie appropriée en fonction des exigences de chargement de votre composant :

    • Utilisez getAsyncLifecycle pour les modales, les espaces de travail, les pages secondaires et les autres composants qui peuvent être chargés à la demande.
    // Bon - modale chargée uniquement lorsque nécessaire export const markPatientAliveModal = getAsyncLifecycle(() => import('./mark-patient-alive.modal'), options);
    • Utilisez getSyncLifecycle pour les composants déjà importés qui doivent être disponibles immédiatement, comme les liens légers, les boutons d’action et les composants racine qui ne doivent pas attendre un autre chunk :
    // Bon - composant inclus dans le bundle principal export const startVisitForm = getSyncLifecycle(startVisitFormComponent, { featureName: 'start-visit-form', moduleName, });

    La différence clé est l’emplacement du code du composant. getAsyncLifecycle utilise un import dynamique, ce qui permet au bundler de créer un chunk séparé qu’O3 ne charge que lorsque le composant est nécessaire. getSyncLifecycle enveloppe un composant déjà importé statiquement ; il reste donc dans le bundle principal du module frontend et est disponible dès que ce module se charge. Évitez de rendre chaque export asynchrone par défaut : beaucoup de petits chunks dynamiques peuvent ajouter des requêtes à l’exécution. Lisez-en plus sur la différence entre les métadonnées statiques et dynamiques ici.

  • Préférez les icônes et pictogrammes exportés par @openmrs/esm-framework lorsqu’un asset OpenMRS correspondant existe. Ils proviennent des sprites du styleguide O3 et évitent d’importer des icônes individuelles depuis @carbon/react/icons quand le système de design fournit déjà l’asset.

  • Envisagez d’utiliser le préchargement pour améliorer la réactivité de votre application. Le préchargement peut être particulièrement utile dans ces cas :

    • Préchargement de données pour les éléments qui sont susceptibles d’être consultés ensuite :
    import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; import { preload } from 'swr'; // Précharger la page suivante de résultats const nextPageUrl = `${restBaseUrl}/patient?startIndex=${currentPage * pageSize}&limit=${pageSize}`; const prefetchNextPage = () => { void preload(nextPageUrl, openmrsFetch); };
    • Préchargement de données en utilisant l’API preload  de SWR lors du survol de liens ou de boutons :
    import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; import { preload } from 'swr'; // Précharger les schémas de formulaire lors du survol de liens dans le form builder <ConfigurableLink className={styles.link} to={editSchemaUrl} templateParams={{ formUuid: form?.uuid }} onMouseEnter={() => form?.uuid && void preload(`${restBaseUrl}/form/${form.uuid}?v=full`, openmrsFetch)} > {form.name} </ConfigurableLink>

    N’oubliez pas que bien que le préchargement puisse améliorer l’expérience utilisateur, il doit être utilisé judicieusement pour éviter les requêtes réseau inutiles et l’utilisation de données.

  • Ajustez votre configuration SWR de manière appropriée pour optimiser les performances. O3 enveloppe les composants des modules frontend dans un openmrsComponentDecorator qui fournit un cache SWR partagé, openmrsFetch comme fetcher par défaut et une configuration SWR globale  qui désactive la plupart des revalidations automatiques. Parce que le composant SWRConfig  fusionne les configurations du contexte parent, vous pouvez surcharger les options dans la configuration globale sur une base par composant. Alternativement, vous pouvez spécifier une configuration personnalisée au niveau de chaque hook. Chaque hook SWR accepte un objet d’options comme argument, que vous pouvez utiliser pour personnaliser le comportement du hook.

    // Simplifié depuis le décorateur de composant OpenMRS const defaultSwrConfig = { // nombre maximum de nouvelles tentatives après l'échec des requêtes errorRetryCount: 3, // fonction fetcher par défaut fetcher: openmrsFetch, // revalider une seule fois toutes les 30 minutes focusThrottleInterval: 1800000, revalidateIfStale: true, // désactiver les revalidations automatiques par défaut revalidateOnFocus: false, revalidateOnReconnect: false, refreshInterval: 0, shouldRetryOnError: (error) => { if (error instanceof OpenmrsFetchError) { const status = error.response.status; if (status >= 500) { return true; } if (status === 401 || status === 403 || status === 429) { return true; } return false; } return true; }, }; <SWRConfig value={defaultSwrConfig}> <ComponentContext.Provider value={this.state.config}> {opts.disableTranslations ? ( <Comp {...this.props} /> ) : ( <I18nextProvider // props omises pour la brièveté > <Comp {...this.props} /> </I18nextProvider> )} </ComponentContext.Provider> </SWRConfig>
    // Configuration au niveau du composant en utilisant le composant SWRConfig <SWRConfig value={{ revalidateOnFocus: true, revalidateOnReconnect: true }}> <Component /> </SWRConfig>
    // Configuration personnalisée au niveau de chaque hook const { data: response } = useOpenmrsSWR<PatientSearchResponse>('/ws/rest/v1/patient?v=full', { swrConfig: { revalidateOnFocus: true, revalidateOnReconnect: true, }, }); const patients = response?.data?.results ?? [];
  • Évitez les pièges de performance courants :

    • Ne créez pas de nouveaux objets ou tableaux dans le rendu lorsqu’ils sont passés à des enfants mémorisés.
    • Évitez les définitions de fonction inline dans JSX lorsqu’elles provoquent le rerender d’enfants mémorisés.
    • N’utilisez pas l’index comme clé dans les listes dont l’ordre peut changer.
    • Empêchez les re-rendus inutiles avec une propriété d’état claire et des props de composant étroites.
    // Mauvais - nouvelle fonction créée à chaque rendu <Button onClick={() => handleClick(id)} /> // Bon - référence de fonction stable const handleButtonClick = useCallback(() => { handleClick(id); }, [id, handleClick]); <Button onClick={handleButtonClick} />
  • Surveillez les performances de votre application en utilisant le React DevTools Profiler . Pour profiler votre application, exécutez à la fois votre application et le shell d’application O3 localement, puis utilisez le mécanisme de surcharge de carte d’import pour charger votre application dans le shell d’application O3. Ouvrez ensuite le React DevTools Profiler dans votre navigateur et démarrez une session de profilage. Les choses à surveiller incluent :

    • Composants avec des re-rendus fréquents
    • Composants qui sont lents à rendre
    • Tâches longues dans le thread principal
    • Composants qui pourraient être mémorisés
Dernière mise à jour le