All posts in iOS

Optimisation des performances Ionic

ionic optimisation

Ionic est un framework open source permettant de développer des applications mobiles hybrides. Pour ce faire, il utilise des technologies web comme HTML, CSS et JavaScript. Il a été lancé en 2013 et a beaucoup évolué depuis.

Evolutions

En 2013, lors de sa sortie, Ionic était fortement lié à AngularJS pour l’interface graphique et à Cordova pour l’accès aux fonctionnalités du téléphone. Depuis, Ionic permet l’utilisation de React, Vue.js et Angular dans leurs dernières versions. Il a également introduit Capacitor pour résoudre les problématiques liées à Cordova.
Avec ses dernières versions, Ionic offre un rendu plus proche des applications natives de chaque plateforme et prend en compte les dernières directives et normes AAA pour l’accessibilité.

Performance

Ionic repose essentiellement sur les WebView (WebView pour Android et WKWebView pour iOS). Par conséquent, les performances de l’application dépendent fortement de celles des WebView, qui ne figurent pas parmi les éléments les plus performants des appareils mobiles.
Les manipulations intensives du DOM peuvent provoquer d’importants ralentissements, notamment sur les appareils d’entrée de gamme.
Une surutilisation des appels aux plugins natifs (via Capacitor) ou une mauvaise configuration de ces derniers peut accroître le temps de réponse et générer de la latence, en raison des interactions entre la couche native et le JavaScript de la WebView.
De plus, l’utilisation de ressources trop volumineuses, telle que des images ou des fichiers CSS/JS, peut également ralentir l’application.

Optimisations

Pour remédier aux problèmes de performance potentiels qu’une application Ionic peut rencontrer, notamment dans le cas d’applications complexes, plusieurs pistes peuvent être envisagées.

Optimisation des ressources

Si votre application est relativement volumineuse, il est recommandé d’envisager l’utilisation du lazy loading pour charger les modules et composants uniquement lorsque cela est nécessaire.

En Angular, il faut utiliser « loadChildren » dans les routes :

export const routes: Routes = [
    {
        path: '',
        component: AppComponent
    },
    {
        path: 'something',
        loadChildren: () => import('./pages/lazy/lazy.routes').then(m => m.routes)
    }
]

Pour la gestion des médias, il est conseillé d’utiliser le lazy loading et de compresser les images avec des formats tels que SVG ou WebP. Il est également souhaitable de limiter le chargement des vidéos et audios sur les écrans inactifs.

Pour la gestion des sources, il est important d’activer la minification des fichiers afin de transmettre des ressources plus légères.

Optimisation de l’interface utilisateur

Lors de l’affichage de longues listes de données, il est recommandé d’utiliser ion-virtual-scroll. Cet élément permet en effet d’afficher de manière optimisée une grande liste en ne rendant visible que les éléments affichés dans la fenêtre de visualisation.

<ion-virtual-scroll [items]="items" approxItemHeight="50px">
  <ion-item *virtualItem="let item">
    <ion-label>
      <h2>{{ item.name }}</h2>
      <p>ID: {{ item.id }}</p>
    </ion-label>
  </ion-item>
</ion-virtual-scroll>

Vous pouvez combiner ion-virtual-scroll avec ion-infinite-scroll pour charger progressivement davantage de données à mesure que l’utilisateur atteint le bas de la liste.

<ion-content>
  <!-- Liste avec défilement virtuel -->
  <ion-virtual-scroll [items]="items" approxItemHeight="50px">
    <ion-item *virtualItem="let item">
      <ion-label>
        <h2>{{ item.name }}</h2>
        <p>ID: {{ item.id }}</p>
      </ion-label>
    </ion-item>
  </ion-virtual-scroll>

  <!-- Chargement progressif -->
  <ion-infinite-scroll threshold="100px" (ionInfinite)="loadMoreData($event)">
    <ion-infinite-scroll-content
      loadingSpinner="bubbles"
      loadingText="Chargement des éléments...">
    </ion-infinite-scroll-content>
  </ion-infinite-scroll>
</ion-content>

Pour les animations, il faut limiter au maximum les animations JavaScript et privilégier les animations CSS natives. Il est également recommandé de privilégier les animations GPU, telles que transform, plutôt que l’utilisation de top/left.

Les manipulations du DOM sont très coûteuses en termes de performance. Il est donc important de limiter l’utilisation de hooks et de directives qui entraînent des modifications fréquentes du DOM.

Optimisation des requêtes réseaux

Étant sur mobile, l’utilisation du réseau peut poser un certain nombre de problèmes, notamment dans les zones blanches ou mal desservies.
Pour résoudre ce problème, il convient de regrouper au maximum les requêtes et, le cas échéant, de compresser les données envoyées et reçues.
Il est également important de mettre en cache les données fréquemment utilisées. On peut ainsi utiliser Ionic Storage, IndexedDB ou @capacitor-community/sqlite. Les deux premiers s’appuient sur les bases de données des navigateurs. Le dernier utilise une base de données native.

Optimisation des performances natives

L’utilisation de fonctionnalités sensibles aux performances (caméra, GPS…) doit passer par des plugins Capacitor bien maintenus. Il faut donc optimiser les appels à ces plugins en les réduisant au minimum.

Optimisations générales

L’optimisation du code, avec la suppression des dépendances inutiles, la suppression des balises HTML superflues et le contrôle de la profondeur des nœuds HTML, permettront d’optimiser votre application.
L’utilisation de techniques avancées, comme le SSR (Server-Side Rendering), permettra d’optimiser les temps de chargement initiaux de l’application. Attention, dans le cadre du SSR, il faut prendre en compte le chargement des données. Lorsque la page est chargée depuis le serveur, on n’a pas accès aux données du navigateur ou aux données natives.
Pour les PWA (Progressive Web App), la configuration des services workers contribuera également à rendre l’expérience hors ligne plus rapide.

Suivi des performances

Dans le cadre du développement, l’utilisation de Chrome DevTools ou Safari Web Inspector permettra d’analyser le temps de rendu et de détecter les goulets d’étranglement de votre application.
Pour analyser les performances directement sur un appareil, vous pouvez utiliser des outils tiers comme Firebase Performance Monitoring ou Sentry.

Si vous souhaitez monter en compétence sur ce framework et travailler sur les performances et l’optimisation Ionic, n’hésitez pas à découvrir notre programme de formation ici.

A lire également notre article sur les Décorateurs TypeScript et Web Components.

KMM : découverte de Kotlin Multiplateform Mobile

Définition

Kotlin Multiplateform Mobile, plus communément appelé KMM, est une technologie open source créée par JetBrains. Stable et en production depuis novembre 2023, elle permet de simplifier le développement multiplateforme, notamment pour Android et iOS.
Le principal langage de programmation de KMM est, comme son nom l’indique, Kotlin. Développé en 2011 par JetBrains, ce langage, moins verbeux que Java, permet une écriture de code plus rapide et concise, offrant une accélération conséquente du rythme de développement. Kotlin propose également des améliorations, notamment avec l’introduction de la null-safety, afin d’éviter les NullPointerException en déclarant des variables pouvant être nulles, assurant ainsi un code plus limpide et robuste. Depuis 2017, il est devenu le langage officiel du développement mobile Android.

Fonctionnement

KMM permet d’intégrer le code métier de l’application de manière partagée entre Android et iOS, réduisant drastiquement le temps de développement et évitant la redondance. Il est utilisé pour écrire les différents modèles de l’application, les appels réseau et aux bases de données. Pour une architecture MVVM, certaines librairies offrent la possibilité de partager également les ViewModels sur les deux supports. Seule la partie visuelle doit être écrite nativement, en XML ou Jetpack Compose pour Android, et en SwiftUI ou UIKit pour iOS, assurant ainsi des performances et une expérience utilisateur optimales.

Exemple

Prenons l’exemple de base d’un projet KMM tout nouvellement créé :

Arborescence KMM (Kotlin Multiplateform Mobile) composeApp : contient le code source de l’application Android en Compose, non partagé.
iosApp : contient le code source de l’application iOS en Swift/SwiftUI, non partagé
shared : contient le code partagé entre les 2 plateformes séparé en 3 dossiers

 

Dans le dossier shared, nous pouvons remarquer la présence des classes et des fichiers Kotlin. Le fichier Platform.kt quant à lui, dans commonMain, contient une interface qui retourne le nom de la plateforme associée au téléphone ainsi qu’une fonction expect. Déclarer une fonction expect permet d’implémenter du code spécifique natif à la plateforme, et c’est pour cela que dans androidMain et dans iosMain, nous retrouvons l’utilisation de cette interface afin de récupérer nativement le nom et le numéro de version de la plateforme. Dans la classe Greeting, nous pouvons appeler une fonction qui nous retournera le nom de la plateforme associée à la fois en Compose sur Android et en SwiftUI sur iOS.

Code KMM (Kotlin Multiplateform Mobile)

Code KMM (Kotlin Multiplateform Mobile)

Conclusion

À l’instar des autres technologies de développement hybride, comme React Native ou Flutter, Kotlin Multiplateform Mobile permet de conserver l’aspect natif de l’application. Il permet en effet d’utiliser les composants et l’expérience des écosystèmes Android et iOS tout en partageant du code métier, alliant à la fois performance de l’application et rapidité de développement. Pour ma part, je trouve que KMM est une véritable innovation dans la création d’applications mobiles natives, permettant d’éviter la redondance d’écriture de code métier lors de la création d’une application Android et iOS. KMM prend dors et déjà de plus en plus d’ampleur au sein des stacks de développement mobile, qu’il s’agissent de nouvelles application ou de refonte.

A noter que les développeurs Android auront forcément plus d’attirance pour cette approche basée sur un langage et un écosystème Kotlin. Cela ouvre également un débat plus organisationnel au sein des équipes mobiles. En effet, il faudra savoir quels développeurs sont ou seront responsables du développement du code partagé.

UIKit vs SwiftUI

UIKit

Pour développer des applications iOS en utilisant le langage Swift ou Objective-C, Apple propose un framework d’interface utilisateur impératif : UIKit. Il permet de construire la partie UI de l’application notamment via l’InterfaceBuilder, l’outil de développement d’interface graphique intégré dans Xcode.
La prise en main de cet outil peut être fastidieuse, et malgré l’habitude, ajouter un simple écran s’avère assez long. Il est tout d’abord nécessaire de glisser et déposer 1 à 1 chacun des composants, pour ensuite les lier entre eux afin de les positionner. Enfin, il faut toujours procéder de la même manière et déclarer ces derniers dans un ViewController.
Pour certains écrans, parfois complexes, cette méthode est chronophage et répétitive. De plus, les écrans créés par cet outil sont intégrés dans un fichier appelé Storyboard, pouvant contenir de multiples interfaces et donc présenter plusieurs inconvénients :

  • Un temps de chargement trop long
  • De nombreux conflits lors de merge (en utilisant Git par exemple)
  • Des composants non-dynamiques et non-adaptables
  • Une interface qui semble désordonnée

Exemple de Storyboard (Source: Swiftement)

Pour pallier ces difficultés, ainsi qu’aux nouveaux designs qui peuvent être plus exigeants, et par conséquent nécessiter un temps de développement plus important, en 2019, Apple a proposé un nouveau framework : SwiftUI.

SwiftUI

Ce nouveau framework d’UI propose une approche déclarative et n’est disponible qu’en Swift. La construction d’un écran se déroule directement dans le code, ce qui est beaucoup plus rapide et compréhensible par les développeurs. Construire une simple interface prendra ainsi peu de temps, chaque écran faisant partie d’un unique fichier (à contrario des Storyboards cités auparavant). Il propose également un canvas interactif permettant de visualiser les changements en temps réel selon plusieurs configurations. Une est notamment utilisée pour l’accessibilité, rappelant ainsi les développements web et mobiles hybrides.

Ce framework peut à la fois être intégré dans des composants UIKit pour ainsi disposer de composants plus dynamiques. De par sa jeunesse, il peut également au contraire intégrer des composants UIKit afin de compenser un certain manque d’adaptabilité. N’étant disponible qu’à partir d’iOS13, certaines applications et téléphones restent évidemment incompatibles avec SwiftUI. Cependant, les versions minimales iPhone sont souvent augmentées pour des raisons de sécurité, rendant ainsi SwiftUI potentiellement supporté par tous les iOS dans un futur proche. A contrario d’UIKit, nécessitant la création d’un nouveau d’un projet en AppKit pour développer une application MacOS, SwiftUI prend lui en charge le multi-device de tous les appareils de la pomme.

UIKit vs SwiftUI : démonstration comparative chronométrée

Prenons l’exemple d’un écran constitué simplement d’un titre et d’un texte, possédant une valeur qui s’incrémente ou se décrémente à l’aide de deux boutons. L’approche de conception est bien différente, avec UIKit, le code n’est utilisé que pour la partie logique de l’application. La partie design se fait via un outil d’interface qui permet de construire notre écran au fur et à mesure, de manière plus contrôlée, mais plus lente. Une bonne partie du temps est utilisée pour parcourir les menus des différents composants. Avec SwiftUI, nous restons sur la même page, en utilisant que très peu la souris et le pad, tout se construisant via le code. Les vidéos accélérées ci-dessous démontrent que l’approche SwiftUI est jusqu’à 2,5 fois plus rapide qu’UIKIt dans cet exemple.

UIKit Demo
SwiftUI Demo

Conclusion UIKit vs SwiftUI

Bien que l’utilisation des deux frameworks puissent s’associer, et qu’UIKit prévale de par son ancienneté, SwiftUI se démarque. En effet, son dynamisme, sa facilité de prise en main ainsi que sa rapidité d’écriture et de conception me permettent, après une réelle utilisation sur projet d’affirmer qu’il représente le futur du développement natif Swift.
Précédemment, j’avais pu développer un projet mobile natif Android en Java et iOS en Swift/UIKit. Je me sentais beaucoup plus à l’aise sur Android et retourner sur xCode m’apparaissait fastidieux et pénible. En effet, avec des temps de chargements longs, de simples écrans à construire pouvaient prendre des heures de travail, pour le même rendu final sur Android, en 3 fois moins de temps. Apprendre et utiliser SwiftUI a donc été, sans l’ombre d’un doute, une vraie bouffée d’air frais. Le framework était certes encore jeune, mais tellement puissant, fluide et dynamique qu’il m’a donné à l’époque l’envie de rouvrir xCode !