Un jeu web qui se charge vite (check-list pratique)
Si les joueurs ne peuvent pas commencer à jouer en quelques secondes, ils s’en vont. Ce tutoriel propose une check-list pratique applicable à presque toutes les piles technologiques de jeux web (Canvas/WebGL/WebGPU, Pixi/Three/PlayCanvas, moteur personnalisé, etc.).
1) Définissez d’abord des budgets (sinon vous ne pourrez pas optimiser)
Choisissez des budgets adaptés à l’appareil ciblé. Voici de bonnes valeurs par défaut pour une expérience de « jeu instantané » :
- JS+CSS transférés : moins de ~300–500 Ko avec gzip (moins, c’est mieux)
- Ressources critiques avant la première interaction : moins de ~2–5 Mo compressés
- Délai avant la première interaction : moins de ~3–5 secondes sur un appareil mobile de milieu de gamme
Notez ces valeurs et considérez-les comme des contrats d’API.
2) Mesurez les bons éléments
Dans les outils de développement Chrome :
- Utilisez Performance pour enregistrer une session et examiner les tâches longues.
- Utilisez Network pour vérifier :
- la taille transférée par rapport à la taille décodée
- les en-têtes de mise en cache
- si les ressources sont diffusées progressivement ou arrivent sous la forme d’un seul énorme bloc
Pour votre jeu, mesurez :
- le délai avant que « le joueur puisse se déplacer »
- le délai avant la « première image significative »
- la « latence de la première interaction » (interaction → image)
Votre intuition concernant la « latence de la première interaction » correspond désormais à une métrique standard : Interaction to Next Paint (INP) a remplacé First Input Delay parmi les signaux web essentiels en mars 2024. Cette métrique mesure le délai complet entre une interaction et l’affichage suivant pour toutes les interactions, et pas seulement la première. Visez un INP inférieur à 200 ms au 75e centile : c’est un point de référence externe utile pour les mesures de réactivité que vous suivez déjà.
3) Compressez tout ce que vous pouvez
Assurez-vous que votre hébergement utilise :
- Brotli (
br) pour les ressources textuelles (JS/CSS/HTML/WASM), lorsqu’il est disponible - gzip comme solution de repli
Si votre hébergeur et votre CDN le permettent, Zstandard (zstd) constitue désormais une troisième option pour Content-Encoding. Il est pris en charge par Chrome et Edge 123+, Firefox 126+ et Safari 26.3+ (soit environ 80 % des utilisateurs) et peut atteindre des taux de compression comparables à ceux de Brotli tout en sollicitant moins le processeur du serveur, ce qui est utile pour les fichiers WASM et JSON volumineux. Les navigateurs n’annoncent Accept-Encoding: zstd que via HTTPS. Conservez donc Brotli et gzip comme solutions de repli pour tous les autres utilisateurs.
Pour les builds WebAssembly, la compression fait souvent toute la différence entre un chargement « instantané » et un jeu qui « ne se charge jamais ».
4) Ne téléchargez pas le monde entier dès le départ
Divisez votre jeu en plusieurs parties :
- Démarrage : chargeur minimal + contrôles + première scène
- Cœur : principaux systèmes de jeu
- Facultatif : niveaux supplémentaires, éléments cosmétiques, textures haute résolution, pistes audio bonus, etc.
Ne chargez le contenu « Facultatif » qu’une fois que :
- le joueur peut déjà jouer, et/ou
- vous savez qu’il souhaite accéder à ce contenu (par exemple, il a atteint un menu ou un niveau)
5) Choisissez les bons formats de ressources
Pour la plupart des jeux web :
- Images : privilégiez WebP (ou AVIF si vous pouvez accepter un encodage plus lent) pour l’interface et les arrière-plans.
- Audio : privilégiez Ogg Vorbis pour un usage général ; testez AAC pour les écosystèmes Apple.
- Vidéo : privilégiez MP4/H.264 pour la compatibilité et WebM lorsqu’il est pris en charge et produit des fichiers plus petits.
Surveillez le coût du décodage : un « téléchargement plus léger » peut malgré tout être « plus lent à décoder ».
6) Gardez votre première scène légère et déterministe
Évitez les éléments suivants dans votre première scène interactive :
- une compilation massive de shaders
- le transfert d’énormes textures
- une génération procédurale qui bloque le thread principal
- l’analyse JSON synchrone de fichiers de plusieurs mégaoctets
Pour les textures en particulier, utilisez KTX2 avec la supercompression Basis Universal plutôt que PNG ou JPEG. Les textures restent compressées pour le GPU après leur transfert (avec transcodage en BC7 sur ordinateur ou en ASTC sur mobile au chargement), ce qui réduit la VRAM nécessaire d’un facteur 4 à 8 et rend les transferts bien moins coûteux que le décodage d’un PNG en pleine résolution suivi de l’envoi des pixels bruts au GPU.
Si vous devez effectuer des opérations lourdes, faites-le :
- progressivement, sur plusieurs images, ou
- dans un Worker (lorsque c’est possible)
7) Mettez en cache de manière intensive (mais correcte)
Utilisez une mise en cache de longue durée pour les ressources adressées par leur contenu :
Cache-Control: public, max-age=31536000, immutable
Pour les points d’entrée HTML, conservez une durée de mise en cache courte afin de pouvoir déployer des mises à jour en toute sécurité.
8) Rendez les échecs rapides et compréhensibles
En cas de problème, affichez :
- un message d’erreur clair
- un bouton pour réessayer
- un lien permettant de signaler le problème
Les échecs silencieux détruisent la confiance.
9) Si vous utilisez des threads Wasm, comprenez COOP/COEP
Si votre build dépend de SharedArrayBuffer (ce qui est courant avec certaines configurations multithreads Wasm), vous aurez probablement besoin d’en-têtes d’isolation interorigine :
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp
Deux options s’offrent à vous pour l’en-tête COEP. require-corp est l’option stricte, mais elle impose à chaque ressource interorigine (textures provenant d’un CDN, scripts tiers) d’envoyer un en-tête Cross-Origin-Resource-Policy, sans quoi elle sera bloquée. Cross-Origin-Embedder-Policy: credentialless permet également d’activer SharedArrayBuffer et l’isolation interorigine, mais charge les ressources interorigine sans identifiants plutôt que de leur imposer une autorisation explicite via CORP. Si vous récupérez des ressources depuis un CDN que vous ne contrôlez pas, credentialless est généralement la solution la moins contraignante.
Effectuez des tests au plus tôt sur votre véritable hébergement, car les en-têtes et les intégrations tierces peuvent provoquer des dysfonctionnements.
10) Rendez le jeu jouable sans SDK
Si vous ciblez le processus de création de Cinevva, visez :
- une URL unique qui démarre de manière fiable
- aucune connexion obligatoire pour lancer une démo
- des contrôles prévisibles
Vous serez alors prêt à distribuer votre jeu sans intégrer de SDK supplémentaire.
À lire également :
- Pour les créateurs de jeux
- Politique relative au contenu généré par l’IA
- Chargement progressif des ressources — modèles de chargement progressif pour les jeux volumineux
- Service workers pour la mise en cache des jeux — mettez les ressources en cache pour des visites ultérieures instantanées
- Comparatif des moteurs de jeux web — taille des builds et temps de chargement selon les moteurs
- Comment publier votre jeu sur itch.io — optimisez les jeux pour navigateur intégrés à itch.io