Constat : avec l’âge nos applications prennent du poids
Avec l’accroissement des possibilités de stockage offertes par les smartphones et l’augmentation de la bande passante disponible, nos apps n’ont cessé de “prendre du poids” au cours du temps. Ce constat a été mis en lumière par deux études de Sensor Tower sur les Apps et les jeux.
Source : SensorTower
Pourquoi faut-il réduire la taille de ses Applications ?
Malgré cette tendance “naturelle” du marché, réduire le poids des applications présente de nombreux avantages :
- réduction de la consommation de données sur les réseaux, permettant aux utilisateurs de télécharger plus rapidement leurs mises à jour (notamment dans le cas d’update obligatoire), mais aussi et surtout de contribuer à un numérique plus sobre et plus écologique
- optimisation de l’espace occupé par l’application dans la mémoire du téléphone
- baisse des coûts de maintenance technique : plus l’application est lourde, plus elle intègre de code et/ou de librairies tierces, sources de coûts de maintenance (mais aussi de bugs)
Optimiser à tous les étages
Une app mobile est une app embarquée, téléchargée sur le terminal de l’utilisateur. L’éditeur va ainsi produire un build qu’il va uploader sur les plateformes des stores (Apple et Google principalement). La plateforme va ensuite adapter le build et le mettre à disposition pour chaque utilisateur, soit pour une première installation, soit pour une mise à jour.
Il faut donc considérer les trois étapes par lesquelles transitent les fichiers et donc réduire :
- la taille de l’application que l’on soumet en tant qu’éditeur sur les stores Apple et Google. L’application uploadée contient notamment les assets pour l’ensemble des devices ciblés (résolutions)
- la taille téléchargée pour le 1er téléchargement d’un utilisateur. Seules les données spécifiques au terminal et à l’OS de l’utilisateur sont téléchargées
- la taille téléchargée pour les mises à jour
Les efforts d'optimisation doivent être réalisés à chaque niveau, sachant que les plateformes font déjà une partie du travail.
Les pistes d’optimisation
Réduire le package en entrée
C’est le principal levier pour l’éditeur : réduire au maximum la taille de son package en entrée. Il peut activer les leviers suivants :
1) Choisir le développement natif
Les framework cross plateform (React Native, Flutter, KMP) sont par nature plus volumineux que l’utilisation du framework natif (Swift / Kotlin) des plateformes.
Les frameworks Cross platform ajoutent au moins 10 à 20 Mo sur un binaire.
En privilégiant le langage natif de la plateforme, on limite également le recours à des librairies externes en s’appuyant sur les librairies natives de la plateforme.
2) Réduire le recours aux dépendances tierces
Les dépendances concentrent le plus souvent l’essentiel du poids d’une application.
Il faut se demander si l’on tire pleinement parti de chacune de ses dépendances ou si, tout simplement, on en a vraiment besoin.
Ainsi, si votre application n’effectue que peu d’appels réseau GET, il n’est probablement pas utile d’intégrer une librairie réseau. Les OS fournissent énormément de ressources de ce côté qui ont fait leurs preuves.
La programmation réactive étant en vogue, il est probable que vous intégriez une des nombreuses dépendances qui implémentent ce principe, tout en n’utilisant qu’une fraction de ses possibilités. Sur Apple, cela peut ainsi être l’occasion de passer à Combine, le nouveau framework d’Apple qui offre des fonctionnalités équivalentes (à condition de ne supporter que les versions supérieures à iOS 13).
Ce ne sont que deux exemples parmi tant d’autres, mais il est intéressant d’appliquer le même raisonnement pour chacune des dépendances.
Ce travail d’optimisation des dépendances tierces permettra, outre la réduction de la taille de l’application, de réduire les coûts de maintenance engendrés par les mises à jour successives, les corrections de bugs ou failles de sécurité, ou tout simplement leur remplacement quand elles sont obsolètes.
Réduire le package téléchargé par l’utilisateur
3) Optimiser la compilation
Les recommandations suivantes sont des paramètres à activer (ou dont il faut vérifier la bonne activation) pour la compilation
a) Sur Android
i) Code Shrinking
Cette phase détecte et supprime en toute sécurité les classes, champs, méthodes et attributs inutilisés de votre application et de ses dépendances (ce qui en fait un outil précieux pour contourner la limite de référence de 64k). Par exemple, si vous n'utilisez que quelques API d'une bibliothèque, la réduction peut identifier le code de la bibliothèque que votre application n'utilise pas et supprimer ce code de votre application.
ii) Resources Shrinking
Tout comme le Code Shrinking, le compilateur va détecter quelles ressources (images, assets, sons, etc.) sont utilisées et supprimera les autres.
iii) Obfuscation
En plus de complexifier le rétro-engineering sur votre application, la phase d’obfuscation réduit considérablement la taille du code en réduisant au possible les noms des classes, variables, méthodes, etc. … de l’application.
b) Sur iOS
Depuis iOS 9, Apple a introduit la notion de bitcode dans le flux de développements des applications iOS. Le bitcode est une représentation intermédiaire d’un programme compilé. C’est un format à mi-chemin entre le code source (Swift, Objective-C) et le code machine (0 et 1). Les applications iOS qui activent le bitcode vont être recompilées par l’App Store, une fois upload, pour la plateforme spécifique qu’elle vise (iOS, iPadOS, etc.).
Mais cet avantage va encore plus loin. L’App Store va optimiser l’application (ce bitcode), mais il pourra à nouveau effectuer cette optimisation de façon automatique sans besoin de resoumettre, lorsque des optimisations du compilateur sont effectuées. Ceux qui ne publient pas de façon régulière peuvent ainsi bénéficier des dernières optimisations sans avoir à resoumettre une application. C’est également pour cette raison que le bitcode est obligatoire pour les applications watchOS et tvOS, afin de pouvoir optimiser régulièrement ces plateformes spécifiques.
Si le bitcode est activé par défaut, il n’est cependant pas toujours opérant. Il y a en effet une contrainte majeure pour activer le bitcode sur iOS : toutes les dépendances utilisées par l’application doivent également l’avoir activé. Cela peut être problématique pour les dépendances propriétaires privées. Le support ou non du bitcode doit ainsi entrer dans les critères de choix d’une dépendance.
4) optimiser la gestion des assets
a) Sur iOS
Cette démarche consiste à ne distribuer que les assets graphiques et à les compresser de manières différenciées en fonction de la version de l’OS et du terminal. Cela permet donc de n’envoyer que les données utiles au terminal, plutôt que d’envoyer toutes les images à tous les terminaux, même celles non compatibles avec l’OS / le terminal.
Sur iOS Les Assets Catalog ont été introduits il y a déjà bon nombre d’années avec Xcode 5 et iOS 7 (2013).
Elles permettent notamment de :
- décliner les ressources images selon le type d’appareil ciblé : par exemple, les écrans ayant une densité de pixel plus importante (iPhone X) se verront utiliser les images fournies en @3x tandis que les écrans à densité plus faible (iPhone XR) se contenteront des images en @2x.
- définir des zones redimensionnables sur certaines images : il est ainsi possible d’obtenir des fonds de bouton plus léger et adaptable à n’importe quelle taille
- bénéficier d’options de compressions selon les types de ressources.
Avec tous ces éléments combinés, l’App Store est capable de proposer des applications contenant uniquement les ressources destinées aux appareils concernés.
Malgré cela, il est important pour les éditeurs de s’assurer que seules les ressources réellement utilisées par l’application soient effectivement intégrées. En effet, Xcode et l’utilisation des Assets Catalog ne permettent pas de s’assurer que les ressources intégrées sont réellement utilisées par l’application.
b) Sur Android
i) Vector Drawable
Les images font partie des points noirs dans la taille d’une application. Se basant sur le principe des densités, il est nécessaire de redéfinir plusieurs fois la même image dans des résolutions différentes pour supporter l’ensemble des téléphones du marché, ce qui génère une taille d’application démesurée par rapport au besoin final.
L’introduction des Vector Drawable permet de contourner cette contrainte.
Se basant sur le format SVG (Scalable Vector Graphic), il les convertit dans un format optimisé au format XML.
On se retrouve avec une seule et unique image qui sera dessinée à la volée en fonction de la densité du téléphone sur lequel est lancée l’application.
Ce format XML contrairement aux fichiers JPG, PNG, qui eux contiennent une donnée brute de l’image, lui contient des coordonnées et instructions de dessin, diminuant leurs poids en majorité à une centaine de kilo-octets au lieu de plusieurs méga-octets.
ii) AAB
Dans cette optique d’optimisation des livrables, Google a conçu un nouveau format, les AAB (Android App Bundles) pour remplacer le vieillissant APK (Android Package).
Ce nous format permet au Google Play Store de se baser sur 3 caractéristiques du téléphone pour générer un APK, à savoir :
- Son architecture.
- La densité de l’écran.
- La langue utilisée.
Cette approche permet d’obtenir :
- Des applications de plus petite taille.
- De consommer moins de bande passante.
- Une installation plus rapide.
- Une consommation moindre de l’espace de stockage du téléphone.
Outre ces optimisations, ce nouveau format offre une sécurité accrue dans la signature des livrables. Il est donc à privilégier désormais.
5) Télécharger les ressources “à la demande”
Pour un parcours lourd en ressources ou pour toutes les ressources peu utilisées, il est possible d’adopter des mécanismes de téléchargement des ressources à la demande.
Une implémentation simple est par exemple de lancer le téléchargement des ressources concernées avant d’afficher le parcours en question, ou encore effectuer ces actions en tâche de fond.
Sur Apple, ce mécanisme est disponible via les “On-Demand Resources”, sur Android via les “Feature Delivery”.
Avec cette implémentation, l’éditeur peut créer un pack de ressources à soumettre sur le Store. Ces ressources ne sont alors pas intégrées à l’application, ce qui allège son poids. L’application pourra ensuite les récupérer séparément et par elle-même lorsqu’elle en aura besoin.
L’adoption des ressources à la demande nécessite un travail spécifique côté application et côté serveur. En effet, il faudra adopter les pré-requis d'Apple / de Google pour l’hébergement de ces ressources afin de pouvoir fonctionner comme l’environnement de production de l’App Store / du Google Play Store.
Les avantages une fois l’application déployée sont toutefois indéniables :
- les ressources pourront être hébergées sur le Store
- le poids de téléchargement de ces packs de ressources sera optimisé avec les mêmes mécanismes que les Assets Catalog (s’ils sont employés)
- du lazy-loading sur les ressources : leur téléchargement n’est lancé qu’au moment opportun
- se couple parfaitement avec les fonctionnalités uniquement actives lors d’achats in-app (exemple : un pack d’emoticones uniquement pour des utilisateurs ayant souscrit à un abonnement).
Réduire le poids des mises à jour
Optimiser le téléchargement différentiel en ne modifiant que les fichiers et dossiers nécessaires.
Lors de la mise à jour des applications, l’App Store effectue une comparaison entre la version installée sur votre appareil et celle que vous souhaitez installée, et crée un delta package. Ce package ne contient que les changements entre les deux versions et est donc optimisé pour avoir un poids le plus bas possible.
Pour tirer parti au maximum de cette fonctionnalité, il est recommandé de ne modifier que les fichiers et dossiers nécessaires, que ce soit le code en lui-même ou les assets. Ainsi un refactoring important, qui n’apporte pas forcément de nouvelles fonctionnalités, peut produire un delta package plus important. Il est donc préférable de garder ce type de modifications pour des mises à jour importantes qui, de toute façon, provoqueront un delta package important.
En pratique comment faire et quels outils ?
La meilleure pratique consiste naturellement à intégrer dans le quotidien de ses développements et de ses choix cette dimension “taille” de l’application.
Des outils existent sur iOS et Android pour faciliter le travail :
Utilisation d’App Store Connect pour iOS
Un rapport du poids des applications existe sur App Store Connect.
Grâce aux optimisations déjà actives par défaut sur votre projet, la taille de votre application sera optimisée selon la plateforme cible. Il est ainsi courant d’avoir une application plus lourde sur iPad ou sur un OS ancien que sur les derniers iPhone ou OS les plus à jour.
Ce rapport peut aussi être généré directement depuis Xcode avant le déploiement de l’application vers l’App Store.
Pour cela, une fois l’archive pour l’application créée, il suffira de l’exporter en application Ad Hoc, Development ou Enterprise et sélectionner les options suivantes. Le rapport de tailles détaillé (App Thining Size Report) sera alors fourni par avec les artefacts de l’application.
Utilisation d’Android Studio
Un mécanisme similaire existe sur Android Studio, basé sur des appareils référents : des indicateurs et des propositions d’optimisations sont disponibles.
Conclusion
Point d’attention au début des Store et des applications, le poids des applications a été rapidement relégué en bas de liste dans la liste des priorités techniques. C’est pourtant un excellent indicateur de la saine gestion technique d’une application : une prise de poids significative de votre application se traduira souvent par une dette technique coûteuse et une augmentation de l’insatisfaction de vos utilisateurs.
L'optimisation du poids des applications mobiles peut ainsi être un excellent sujet pour marier les objectifs de satisfaction utilisateurs, de sobriété numérique et de réduction des coûts de maintenance technique.
Nous vous encourageons ainsi à mener une étude sur l’optimisation du poids de vos applications et à s’assurer que celui-ci n’évolue pas significativement à la hausse avec le temps.
Vincent Frattaroli
Inside App