Accueil > Non classé > Découper le chargement d’une application Flex

Découper le chargement d’une application Flex

Un projet Flex standard produit un seul fichier SWF. Dans le cas de gros projets, cela peut aboutir à un projet monolithique composé d’un trop grand nombre de classes et lignes de code à maintenir, mais également  à un temps de chargement assez important chez l’utilisateur.

L’objectif de cet article est de présenter un ensemble de solutions permettant de découper une application Flex en plusieurs fichiers à des fins d’amélioration du développement et d’optimisation des temps de chargement. On restera ici assez général, l’idée étant plus de résumer les différentes solutions existantes que de présenter les manières pour les mettre en place. Cela fera plutôt l’objet d’autres articles…

Dans un premier temps, nous allons procéder à un rappel des étapes composant la compilation d’une application Flex, afin d’avoir les connaissances nécessaires pour discuter découpage d’application et autre technique de charcuterie.

Partie 1 : la compilation d’une application Flex

A l’instar de projets Java, un projet Flex est dans un premier temps compilé en bytecode puis interprété par la machine virtuelle Flash.

La compilation permet de convertir des classes ActionScript/MXML et diverses ressources (bibliothèques de composants (fichiers SWC), images embarquées, feuilles de style CSS, etc.) en  fichier SWF. Le processus de compilation suit plusieurs étapes :

- étape 1 : conversion des composants MXML (fichiers .mxml) en classes ActionScript (fichiers .as). Pour les plus curieux, il est possible de dire au compilateur avec l’option -keep-generated-actionscript de garder les fichiers générés lors de cette étape : dans le FlexBuilder, allez dans “propriétés du projet” -> “compilateur flex” et rajoutez -keep-generated-actionscript dans les paramètres additionnels de compilation

- étape 2 : conversion des classes ActionScript en bytecode.

- étape 3 : construction du fichier SWF à partir du bytecode généré (dans l’étape précédente ou à partir d’un fichier SWC) et des ressources statiques, en utilisant ou pas un rapport de liens (fichier xml décrivant des classes, utilisable en configurant le compilateur de la sorte : -load-externs=report.xml) et les dépendences statiques vers des bibliothèques SWC.

Pour ceux qui se demandent ce que j’entends par “ressources statiques”, sachez qu’il existe deux méthodes pour lier une ressource à une application SWF : la liaison statique et la liaison dynamique.

La liaison statique (static linking) implique que le compilateur inclut la ressource dans le fichier SWF produit. Une application entièrement compilée de cette façon aura un temps de chargement initial relativement long, puisque l’ensemble des ressources sont incluses dans le fichier produit, mais sera plus réactive une fois chargée, car il n’y aura pas de classes ou ressources à aller chercher par la suite.


staticlinking


La liaison dynamique (dynamic linking) est le cas où certaines ressources utilisées par l’application sont placées dans des fichiers externes et chargées à l’exécution. Cela permet de produire un fichier SWF plus petit, mais cela rend l’application dépendante d’autres fichiers.

Flex Dynamic linking

Partie 2 : découpage d’une application côté développeur

C’est une partie sur laquelle je vais passer assez vite, car elle constitue simplement un rappel de ce qui existe en terme de bonnes pratiques de développement.

1. Utiliser les packages

Même au sein d’un projet unique, il est possible de séparer différents morceaux de code grâce aux packages. Cela permet de structurer le projet en fonction du rôle auquel les classes/composants MXML sont destinés.

2. Créer des bibliothèques de composants

De la même manière qu’il existe en Java des JARs, en C/C++ des DLLs, etc… on peut regrouper des classes dans des bibliothèques en Flex :  il s’agit des fameux fichiers SWC.

Les fichiers SWC sont en fait des archives simples contenant un descripteur au format XML et le bytecode des classes dans un fichier “library.swf”.

Il est à noter que lorsqu’on crée dans un projet des dépendances vers des bibliothèques SWC, il est possible de spécifier la nature du lien : “merged with code” (inclut dans le fichier SWF produit), externe (ne sera pas inclut dans le SWF produit) ou RSL (ne sera pas inclut dans le SWF produit, mais avec quelques subtilités qui seront évoquées ultérieurement).

Partie 3 : découpage d’une application côté client

Cette partie traite plus spécifiquement de ce qui profite au client, c’est à dire la personne qui va charger votre application. Le découpage permet au client de charger progressivement une application, plutôt que de charger un gros SWF de plusieurs méga-octets alors qu’un utilisateur standard n’utilisera pas la moitié des fonctionnalités chargées.

1. Sous applications autonomes

Ceci est le cas le plus simple pour découper une application en plusieurs fichiers. Si dans un projet on retrouve des blocs logiques indépendants les uns des autres, il peut être intéressant de créer plusieurs sous-projets qui seront chargés par une application parente ou même en utilisant différentes URLs.

L’avantage de cette méthode est que le client n’est pas obligé de charger d’un seul coup tout ce qui compose notre application s’il veut uniquement utiliser une certaine fonctionnalité.

Cette méthode souffre cependant de plusieurs inconvénients majeurs, tant pour le développement que pour le déploiement. Il est en effet très difficile de faire communiquer la sous-application ainsi chargée et l’application parente (si le besoin s’en fait sentir). Et si les sous-applications dépendent de code commun, celui-ci sera compilé dans chacune des sous-applications, augmentant la taille globale de l’application.

2. Les modules Flex : des sous-applications presque autonomes

Les modules Flex (héritant de la classe de base mx.modules.Module) permettent de faire exactement la même chose qu’avec des sous-applications autonomes, mais avec quelques subtilités.

Pour commencer, les modules nécessitent l’utilisation d’une classe parente. Il n’est pas possible de les lancer tout seuls, malgré le fait qu’il s’agisse de fichiers SWF.

Pour l’application parente, les modules ne sont pas vus comme des fichiers autonomes, mais comme une sous partie de celle-ci. Côté développeur, c’est comme si on développait une application compilée en un seul gros fichier,  mais le compilateur se débrouille pour casser celle-ci à la compilation. Les modules sont donc liés dynamiquement à l’application parente, et chargés au besoin au cours de l’exécution. Les modules bénéficient également du contexte de l’application parente : il est possible d’utiliser des variables, paramètres statiques, singletons, etc. définis et initialisés par l’application parente au sein du module.

Le principal avantage des modules est que la communication avec l’application parente est grandement facilitée : par un jeu d’interfaces, il est très facile de faire communiquer les deux.

De plus, grâce à une option de compilation (permettant d’utiliser les rapport de liens, cf. la première partie), un module peut ne pas inclure à la compilation les symboles déjà compilés dans l’application parente, ce qui évite (à une certaine échelle) d’alourdir l’ensemble de l’application en chargeant des classes en doublons.

3. Les Runtime Shared Libraries : charger des symboles à l’initialisation de l’application

Nous avons parlé dans la partie 2 de l’utilisation de bibliothèques de composants SWC. Dans le projet principal (celui qui produit un fichier SWF), spécifier la nature d’une dépendance à RSL veut dire que les classes contenues dans la bibliothèque ne seront pas incluses dans le SWF, mais aussi que cette bibliothèque sera absolument nécessaire pour que l’application s’initialise, et donc que cette bibliothèque devra être accessible sur le réseau.

Mais attention, sur le réseau votre application SWF ne va pas rechercher un fichier SWC, mais un fichier SWF portant le même nom que votre bibliothèque qui correspond au fichier library.swf inclut dans celle-ci (cf partie 2).

Les RSLs sont des épées à double tranchant : lors d’une compilation classique, seules les classes utilisées sont incluses dans le livrable final, ce qui veut dire que l’utilisateur ne chargera pas de classes inutilisées par l’application. Utiliser les RSLs implique que l’utilisateur va charger l’ensemble de la bibliothèque avant de pouvoir utiliser votre application. L’énorme avantage de cette manière de faire est l’utilisation du cache du navigateur pour charger des bouts de l’application : si votre bibliothèque ne change pas, l’utilisateur n’aura pas besoin de la recharger tant qu’il ne vide pas son cache. L’inconvénient sera donc le temps de chargement initial de la bibliothèque, et seulement après le chargement de l’application sera plus rapide.

Conclusion

Nous avons découvert à travers cet article un certain nombre de procédés pour découper une application Flex. Il n’y a pas de méthode qui soit meilleure que l’autre, car elles répondent chacune à des besoins différents :

  • travailler à plusieurs sur une application (structure du projet, bibliothèques de composants… )
  • charger progressivement des briques applicatives en fonction des cas d’utilisation (sous-applications, modules)
  • mettre à profit le cache navigateur pour ne charger que les morceaux de l’application qui ont changé (RSLs)

Et comme toutes les bonnes choses, il ne faut pas en abuser ;)

Share
  1. Pierre-Yves RICAU
    11/01/2010 à 13:10 | #1

    Merci pour ce tour d’horizon, le temps de chargement des applications Flex est bien souvent problématique…

    Je me pose une question : dans le cas du découpage en modules, tu indiques que cela génère différents fichiers SWF. Cela signifie-il qu’on bénéficie du cache du navigateur, au même titre que pour les RSL ?

    Par ailleurs, est-il possible de charger les modules complémentaires en tâche de fond, et conditionnellement ? Je m’explique : supposons que l’application ait une interface d’admin à laquelle seuls certains utilisateurs ont accès. Peut-on imaginer lancer le chargement du module en tâche de fond, avant même que l’utilisateur ouvre la partie admin, et uniquement s’il a les rôles nécessaires ? Cela permettrait d’une part d’éviter un temps de chargement lors de l’ouverture de cette partie admin, et d’autres part de commencer à utiliser l’application en parallèle.

    • Alnour GOULAMHOUSSEN
      11/01/2010 à 14:49 | #2

      @Pierre-Yves RICAU Comme les modules sont compilé dans différents objets SWF, il est effectivement possible d’utiliser le cache du navigateur. Et concernant le chargement du module à l’exécution, la méthode de chargement est laissé à la libre appréciation du développeur: on peut donc, en fonction des droits de l’utilisateur, charger le module à l’initialisation de l’application, lors de la première tentative d’accès, ou en arrière-plan quand l’application est peu sollicitée.

  1. Pas encore de trackbacks