Sert les couvertures depuis IndexedDB aussi en ligne, et libère les blob:
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2548,3 +2548,57 @@ jamais « créer une revue », c'est toujours « ranger un numéro ».
|
||||
|
||||
Vérifié en exécution : `9772466671438` saisi depuis « Ajouter un ouvrage » nomme toujours
|
||||
« Médor » et propose d'ouvrir sa fiche.
|
||||
|
||||
## Les couvertures viennent du cache AUSSI en ligne — règle A5 renversée (2026-08-20)
|
||||
|
||||
Constat d'usage : sur téléphone, après un rechargement, les vignettes n'apparaissent pas tout de
|
||||
suite — alors que deux couvertures dont l'URL avait été collée à la main (CDN de la Fnac)
|
||||
s'affichaient sans attendre.
|
||||
|
||||
⚠️ **L'hypothèse naturelle était fausse, et c'est ce qu'il faut retenir** : « garder l'URL en base
|
||||
pour charger plus vite » ne pouvait rien donner — `Livre.CoverUrl` **est** en base depuis
|
||||
toujours, il n'y avait aucune résolution à supprimer. La comparaison avec la Fnac désignait la
|
||||
vraie cause : `covers.openlibrary.org` répond **302, deux fois**, avant d'aboutir sur
|
||||
`archive.org` (déjà mesuré au lot du relais), là où une URL de CDN va droit au fichier. Trois
|
||||
allers-retours par vignette, dix vignettes à l'écran, sur un lien mobile.
|
||||
|
||||
Seconde cause, dans notre code : `Couverture.razor` ne lisait le magasin IndexedDB `couvertures`
|
||||
que **hors ligne**. En ligne, chaque rechargement repartait du réseau pour une image déjà rangée
|
||||
sur l'appareil.
|
||||
|
||||
**Décidé avec l'utilisateur : le cache est consulté d'abord, en ligne comme hors ligne. Le réseau
|
||||
n'est sollicité que si rien n'est en cache.**
|
||||
|
||||
⚠️ **Ceci renverse la règle du lot A5** — « en ligne, l'affichage utilise l'URL réseau telle
|
||||
quelle : rien ne doit ralentir la voie rapide ». Elle n'était pas absurde, elle était mal
|
||||
calibrée : ce qu'on protégeait était une requête réseau avec redirections, ce qu'on refusait
|
||||
était une lecture IndexedDB locale. La seconde est largement plus rapide que la première. Le
|
||||
sens du mot « rapide » avait été supposé, pas mesuré.
|
||||
|
||||
Le fire-and-forget de mise en cache subsiste, mais **seulement quand le cache est vide** : rien
|
||||
ne sert de le relancer pour une image déjà rangée (`couvertureMettreEnCache` court-circuitait
|
||||
déjà sur son `getKey`, c'est maintenant explicite côté C#).
|
||||
|
||||
### ⚠️ Le corollaire à ne pas oublier : révoquer les `blob:`
|
||||
|
||||
`URL.createObjectURL` retient son Blob en mémoire **jusqu'à révocation ou fermeture de la page**.
|
||||
Tant que le cache ne servait qu'hors-ligne, la fuite restait bornée à une consultation
|
||||
ponctuelle ; avec une vignette par carte sur tous les écrans, elle ne l'est plus. `Couverture`
|
||||
implémente donc `IAsyncDisposable` et libère aussi lorsqu'elle change d'URL
|
||||
(`couvertureLiberer` → `URL.revokeObjectURL`).
|
||||
|
||||
### Vérifié en exécution
|
||||
|
||||
| Point | Résultat |
|
||||
|---|---|
|
||||
| `src` des vignettes au chargement | **`blob:`** pour les deux couvertures |
|
||||
| Requêtes vers `editions-ambre.fr`, `openlibrary.org`, `/api/couvertures` | **aucune** |
|
||||
| Contenu réellement servi par le `blob:` | `image/jpeg`, 15 777 o, **500×500** |
|
||||
| URL d'objet après navigation vers un autre écran | **révoquée** (fetch rejeté) |
|
||||
|
||||
479 tests au vert.
|
||||
|
||||
⚠️ `naturalWidth` reste à 0 dans le navigateur d'automatisation : la fenêtre ne compose pas
|
||||
d'image, donc `loading="lazy"` ne déclenche jamais le décodage. Ce n'est pas un défaut de la
|
||||
couverture — le blob a été décodé à la main par `createImageBitmap` pour le prouver. Ne pas
|
||||
partir en chasse là-dessus.
|
||||
|
||||
Reference in New Issue
Block a user