Comme vous le savez, l'image de Boo (la mascotte en haut à gauche des pages) change en fonction de la date et de la météo. Ce mécanisme fait pour l'instant partie du site, mais j'aimerais bien le remplacer pour permettre à ceux qui savent en dessiner d'en ajouter de nouvelles variantes sans avoir besoin de passer par moi. J'envisage de faire ça au moyen d'un site séparé, déployé indépendamment, dont le seul rôle est de définir l'image à afficher et l'éventuelle animation associée. Mon problème c'est que je n'arrive pas à faire ça sans dégrader le rendu du site à cause de clignotements ou de pages plus lentes à charger.
Le fonctionnement aujourd'hui
Actuellement c'est yAronet qui, à chaque affichage de page, peut déterminer quelle variante de Boo afficher et donc insérer directement la bonne URL dans la page. Un JavaScript s'occupe de la partie animation, s'il y a une animation définie pour le Boo sélectionné (par exemple le Boo "arbre de noël" affiché en ce moment). Ce script est chargé de façon asynchrone sur la page, ce qui signifie que l'animation démarre potentiellement que quelques millisecondes après que la page est chargée ce qui ne pose aucun problème puisque les animations sont lissées et sans transitions brutales. Le JavaScript est statique (pour favoriser sa mise en cache), c'est à dire qu'il ne dépend pas du Boo sélectionné. Pour savoir quel Boo est actif, il compare seulement l'URL de l'image avec celles qu'il connait pour savoir si une animation doit être démarrée.
En gros, ça fonctionne comme ça :
Pseudo-code du fonctionnement actuel
Page affichée par yAronet :
Script d'animation :
<img id="boo" src="boo/noel.png" />
<script type="text/javascript" src="boo/animation.js" async></script>
Script d'animation :
var boo = document.getElementById('boo');
switch (baseNameWithoutExtension(boo.src))
{
case 'noel':
startNoelAnimation();
break;
}
Ce que j'avais envisagé de changer
Comme je le disais plus haut, je pensais déplacer ce fonctionnement dans un site dédié, qui serait responsable de choisir quel Boo afficher et s'occuper de servir à la fois l'image et le code JavaScript. yAronet se contenterait de référencer deux URLs vers ce nouveau service mais ne choisirait plus quel Boo doit être affiché. Voilà à quoi ça pourrait ressembler :
Pseudo-code du fonctionnement envisagé
Page affichée par yAronet :
Script PHP de sélection d'image "image.php" :
Le script d'animation resterait inchangé.
<img id="boo" src="http://boo.yaronet.org/image.php" />
<script type="text/javascript" src="http://boo.yaronet.org/animation.js" async></script>
Script PHP de sélection d'image "image.php" :
'Location: http://boo.yaronet.org/boo/' . $boo . '.png');
$boo = selectCurrentBooVariant();
header(Le script d'animation resterait inchangé.
Le problème des deux requêtes
Le problème que je viens d'identifier peut se résumer facilement : je dois faire deux requêtes (une pour l'image et une pour le JavaScript) dont une seule va calculer quel Boo doit être affiché, mais l'autre doit pouvoir en tenir compte. Cette contraire vient du fait que ce calcul n'est pas gratuit (je fais appel à deux APIs dont le nombre de requêtes est limité pour connaître la météo) donc je ne peux pas le faire en double. D'autre part, même si je le faisais en double je risquerais d'avoir deux réponses différentes (par exemple lors d'un changement d'heure ou à la seconde précise où la météo change) et donc d'avoir des incohérences entre les résultats des deux requêtes.
En pratique il y a déjà une mise en cache de 15 minutes pour éviter d'appeler ces APIs à chaque page, mais je ne vois pas comment partager ce cache entre les deux requêtes. Si me débrouille par exemple pour que image.php écrive un cookie qui pourra être lu par le code JavaScript ça ne fonctionne pas, puisque le cookie se retrouverait sur le domaine boo.yaronet.org tandis que le script s'exécute sur www.yaronet.com. Des iframes ne sont pas envisageables puisque la taille de Boo n'est pas connue à l'avance.
Mes autres pistes clignotent
Bon, si je pars du principe qu'une seule de mes deux requêtes peut déterminer quel Boo à afficher et que la seconde doit se débrouiller pour le déduire sans refaire les calculs, ça limite pas mal mes options. Au lieu d'avoir une image dynamique et un script statique je peux faire l'inverse : générer un code JavaScript qui connait l'URL du Boo à afficher, et qui s'occupe de provoquer le chargement de la bonne image quand il s'exécute :
Pseudo-code de la solution avec JavaScript dynamique
Page affichée par yAronet :
Code PHP d'animation :
<img id="boo" />
<script type="text/javascript" src="boo/animation.php" async></script>
Code PHP d'animation :
// On calcule le Boo à afficher et on construit dynamiquement le code JavaScript adapté
$boo = selectCurrentBooVariant();
$code = "var boo = document.getElementById('boo');
boo.src = 'http://boo.yaronet.org/boo/" . $boo . ".png';
switch (baseNameWithoutExtension(boo.src)) /* On pourrait même évaluer ce switch dès maintenant, mais ça ne simplifierait pas le problème */
{
case 'noel':
startNoelAnimation();
break;
}";
// On envoie le tout comme s'il s'agissait d'un JavaScript
header('Content-Length: ' . strlen($code));
header('Content-Type: text/javascript');
echo $code;
En plus je n'ai pas tellement envie de faire ça, parce que déterminer quel Boo afficher prend quand même le temps de faire les appels à deux APIs (c'est à dire de l'ordre de quelques centaines de millisecondes). Ça n'arrive qu'une seule fois toutes les 15 minutes et le reste du temps tout est en cache donc l'affichage est quasi-instantané, mais j'aimerais quand même bien ne pas impacter le chargement de la page avec ça. Au passage, c'est le seul petit défaut de la solution actuelle que j'essaie de corriger au passage.
Bloqué !
Je pense que j'ai résumé mes tentatives actuelles, et pour le moment je bloque un peu. Est-ce que vous voyez une autre piste ? C'est rageant d'être bloqué pour un détail qui semble aussi simple
