Créer un jeu WebGL multiplateforme avec Babylon.js
Publié: 2022-03-10Voici un défi pour vous : que diriez-vous de créer un jeu en 3D pendant le week-end ? Babylon.js est un framework JavaScript pour créer des jeux 3D avec HTML5, WebGL et Web Audio , construit par votre serviteur et l'équipe Babylon.js. Pour célébrer la nouvelle version 2.3 de la bibliothèque, nous avons décidé de créer une nouvelle démo nommée "Sponza" pour mettre en évidence ce qui peut être fait avec le moteur WebGL et HTML5 lorsqu'il s'agit de créer de grands jeux de nos jours.
L'idée était de créer une expérience cohérente, similaire, voire identique, sur toutes les plates-formes prises en charge par WebGL et d'essayer d'atteindre les fonctionnalités des applications natives. Dans cet article, j'expliquerai comment tout cela fonctionne ensemble, ainsi que les différents défis auxquels nous avons été confrontés et les leçons que nous avons apprises lors de sa construction.
Lectures complémentaires sur SmashingMag :
- Construire des shaders avec Babylon.js
- Utilisation de l'API Gamepad dans les jeux Web
- Introduction à la modélisation polygonale et à Three.js
- Comment créer une boîte à rythmes 8 bits réactive
Pour atteindre cet objectif, Sponza utilise un certain nombre de fonctionnalités HTML5 telles que WebGL, Web Audio, ainsi que Pointer Events (largement pris en charge maintenant grâce à jQuery PEP polyfill), Gamepad API, IndexedDB, HTML5 AppCache, CSS3 transition/animation, flexbox et Fullscreen API. Vous pouvez tester la démo Sponza sur votre ordinateur de bureau, mobile ou Xbox One.

Découvrir la démo
Tout d'abord, vous commencerez sur une séquence auto-animée donnant les crédits à celui qui a construit la scène. La plupart des membres de l'équipe viennent de la scène démo. Vous découvrirez qu'il s'agit d'une partie importante de la culture des développeurs 3D. De mon côté, j'étais sur Atari tandis que David Catuhe était sur Amiga qui est toujours une source régulière de conflits entre nous, croyez-le ou non. Je codais un peu mais je composais principalement la musique dans mon groupe de démo. J'étais un grand fan de Future Crew et plus particulièrement de Purple Motion, mon compositeur de scène de démo préféré de tous les temps. Mais ne nous éloignons pas du sujet.
Pour Sponza, voici les contributeurs :
- Michel Rousseau alias "Mitch" a réalisé des animations visuelles remarquables et des optimisations de rendu en tant qu'artiste 3D. Il a pris le modèle Sponza fourni gratuitement par Crytek sur leur site Web et a utilisé l'exportateur 3DS Max pour générer ce que vous voyez.
- David Catuhe alias "deltakosh" et moi avons réalisé la partie centrale du moteur Babylon.js et également tout le code de la démo (chargeur personnalisé, effets spéciaux pour le mode démo utilisant des post-processus de fondu au noir, etc.) ainsi que un nouveau type de caméra nommé « UniversalCamera » gérant tous les types d'entrées de manière générique.
- J'ai composé la musique en utilisant Renoise et la banque de sons EastWest Symphonic Orchestra. Si cela vous intéresse, j'ai déjà partagé mon flux de travail et mon processus dans l'article sur la composition de la musique pour le jeu World Monger Windows 8 à l'aide du tracker Renoise et des plug-ins East West VST
- Julien Moreau-Mathis nous a aidés en construisant un nouvel outil pour aider les artistes 3D à finaliser le travail entre les outils de modélisation (3DS Max, Blender) et le résultat final. Par exemple, Michel l'a utilisé pour tester et régler diverses caméras animées et pour injecter des particules dans la scène.
Si vous attendez la fin de la séquence automatique jusqu'à la «fin épique», vous serez automatiquement basculé en mode interactif. Si vous souhaitez contourner le mode démo, cliquez simplement sur l'icône de l'appareil photo ou appuyez sur A
sur votre manette de jeu.
En mode interactif, si vous êtes sur Mac ou PC, vous pourrez vous déplacer dans la scène à l'aide du clavier/souris comme un jeu FPS. Si vous êtes sur un smartphone, vous pourrez vous déplacer en utilisant une seule touche (et 2
pour faire pivoter la caméra). Enfin, sur une Xbox One, vous pouvez utiliser la manette de jeu (ou le bureau si vous y branchez une manette de jeu). Fait amusant : sur un PC tactile Windows, vous pouvez potentiellement utiliser 3 types de saisie en même temps.
L'ambiance est différente en mode interactif. Vous avez trois sources audio de tempête positionnées au hasard dans l'environnement 3D, des coups de vent et des fissures de feu à chaque coin. Sur les navigateurs supportés (Chrome, Firefox, Opera et Safari), vous pouvez même basculer entre le mode haut-parleur normal et le mode casque en cliquant sur l'icône dédiée. Il utilisera ensuite le rendu audio binaural de Web Audio pour une simulation audio plus réaliste - si vous écoutez au casque.
Pour avoir une expérience complète de type application, nous avons généré des icônes et des vignettes pour toutes les plateformes. Cela signifie, par exemple, que sur Windows 8 ⁄ 10 , vous pouvez épingler l'application Web dans le menu "Démarrer". Nous avons même plusieurs tailles disponibles :


Hors ligne d'abord !
Une fois la démo complètement chargée, vous pouvez passer votre téléphone en mode avion pour couper la connectivité et cliquer sur l'icône Sponza. L'application Web fournira toujours l'expérience complète avec le rendu WebGL, l'audio Web 3D et la prise en charge tactile. Basculez-le en plein écran et vous ne pourrez littéralement pas sentir la différence entre la démo et une expérience d'application native.
Nous utilisons la couche IndexedDB disponible nativement dans Babylon.js pour cela. La scène (format JSON) et les ressources (textures JPG/PNG ainsi que MP3 pour la musique et les sons) sont stockées dans IDB. La couche IDB couplée au cache d'application HTML5 fournit alors l'expérience hors ligne. Pour en savoir plus sur cette partie et comment configurer votre jeu pour obtenir des résultats similaires, vous pouvez lire l'article sur l'utilisation d'IndexedDB pour gérer vos actifs WebGL 3D : partager les retours et astuces de Babylon.JS et mettre en cache les ressources dans IndexedDB dans Babylon.js
Xbox One profite du spectacle
Enfin, la même démo fonctionne parfaitement dans MS Edge sur votre Xbox One :

Appuyez sur A
pour passer en mode interactif . La Xbox One vous informera que vous pouvez désormais vous déplacer à l'aide de votre manette de jeu dans la scène 3D :

Alors, récapitulons brièvement.
La même base de code fonctionne sur Mac, Linux, Windows sur MS Edge, Chrome, Firefox, Opera et Safari, sur iPhone/iPad, sur les appareils Android avec Chrome ou Firefox, Firefox OS et sur Xbox One ! N'est-ce pas cool? Pouvoir cibler autant d'appareils avec une expérience native à part entière directement depuis votre serveur Web ?
J'ai déjà partagé mon enthousiasme quant au potentiel de la technologie dans un précédent article sur Le web : la prochaine frontière du jeu ?
Hackez la scène avec la couche de débogage
Si vous souhaitez comprendre comment Michel maîtrise la magie de la modélisation 3D, vous pouvez pirater la scène à l'aide de l'outil Babylon.js Debug Layer . Pour l'activer sur une machine avec un clavier, appuyez sur CMD/CTRL + SHIFT + D
et si vous utilisez une manette sur PC ou Xbox, appuyez sur Y
. Veuillez noter que l'affichage de la couche de débogage coûte un peu de performance en raison du travail de composition que le moteur de rendu doit effectuer. Ainsi, les FPS affichés sont un peu moins importants que les FPS réels que vous avez sans la couche de débogage affichée.
Testons-le sur un PC, par exemple.
Déplacez-vous près de la tête de lion et coupez le canal de bosse du pipeline de notre shader :

Vous devriez voir que la tête est maintenant moins réaliste. Jouez avec l'autre chaîne pour vérifier ce qui se passe.
Vous pouvez également couper le moteur de foudre dynamique ou désactiver le moteur de collisions pour voler ou vous déplacer à travers les murs. Par exemple, désactivez la case à cocher " collisions " et volez jusqu'au premier étage. Placez la caméra devant les drapeaux rouges. Vous pouvez les voir bouger légèrement. Michel a utilisé le support des os/squelettes de Babylon.js pour les déplacer. Maintenant, désactivez l'option « squelettes » et ils devraient cesser de bouger :

Enfin, vous pouvez afficher l'arbre des mailles dans le coin supérieur droit. Vous pouvez les activer ou les désactiver pour casser complètement le travail effectué par Michel :

Supprimer les géométries, les canaux du shader ou certaines options du moteur peut vous aider à dépanner les performances sur un appareil spécifique pour voir ce qui coûte actuellement trop cher. Vous pouvez également vérifier si vous êtes limité par le CPU ou par le GPU, bien que la plupart du temps, vous serez limité par le CPU dans WebGL en raison de la nature mono-threading de JavaScript. Enfin, l'outil est également très utile pour vous aider à comprendre comment une scène a été construite par l'artiste 3D.
Au fait, cela fonctionne plutôt bien sur Xbox One aussi :

Défis
En cours de route, nous avons rencontré un certain nombre de problèmes et de défis pour construire la démo. Examinons certains d'entre eux en détail.
Performances WebGL et compatibilité multiplateforme
Le côté programmation était probablement le plus facile à aborder car il est entièrement géré par le moteur Babylon.js lui-même. Nous utilisons une architecture de shader personnalisée qui s'adapte à la plate-forme en essayant de trouver le meilleur shader disponible pour le navigateur/GPU actuel en utilisant diverses solutions de repli. L'idée est de réduire la qualité et la complexité du moteur de rendu jusqu'à ce que nous parvenions à afficher quelque chose de significatif à l'écran.
Babylon.js est principalement basé sur WebGL 1.0 pour garantir que les expériences 3D construites dessus fonctionneront à peu près partout. Il a été construit avec la philosophie Web à l'esprit, nous améliorons donc progressivement le processus de compilation des shaders. C'est complètement transparent pour l'artiste 3D qui ne veut pas faire face à ces complexités la plupart du temps.
Pourtant, l'artiste 3D a un rôle très important dans l'optimisation des performances. Elle doit connaître la plate-forme qu'elle cible, les fonctionnalités prises en charge et les limitations. Vous ne pouvez pas prendre des actifs provenant de jeux AAA conçus pour les GPU haut de gamme et DirectX 12 et simplement les intégrer dans un jeu fonctionnant sur un moteur WebGL. Je dirais que cibler WebGL aujourd'hui est assez similaire au travail que vous devrez faire pour optimiser les expériences sur les appareils mobiles, avec une touche de JavaScript supplémentaire qui doit être hautement mono-thread.
Mitch est extrêmement doué pour cela : optimiser les textures, pré-calculer la foudre pour l'intégrer aux textures, réduire autant que possible le nombre d'appels de tirage, etc. Il a des années d'expérience derrière lui et a vu les différentes générations de Matériel et moteurs 3D (de PowerVR/3DFX aux GPU d'aujourd'hui) qui ont vraiment aidé à réaliser la démo.
Il a déjà partagé un peu de ces bases dans ses articles sur la 3D en temps réel : faire une démo pour WebGL Purposes–Basics et a déjà prouvé à plusieurs reprises que vous pouvez créer une expérience visuelle assez fascinante sur le Web avec des performances élevées sur de petits GPU intégrés, par exemple dans Scènes de démonstration Mansion, Hill Valley ou Espilit. Si ça vous intéresse, prenez le temps de regarder sa conférence sur NGF2014 – Créer des assets 3D pour le monde mobile & le web, le point de vue d'un designer 3D où il a partagé son expérience et comment il a réussi à optimiser la scène Hill Valley de moins de 1 fps à 60 fps.

L'objectif initial de Sponza était de construire deux scènes. Un pour le bureau et un pour le mobile avec moins de complexité, des textures plus petites et des maillages et géométries plus simples. Mais lors de nos tests, nous avons finalement découvert que la version de bureau fonctionnait également assez bien sur mobile puisqu'elle peut fonctionner jusqu'à 60fps sur un iPhone 6s ou un Android OnePlus 2. Nous avons alors décidé de ne pas continuer à travailler sur la version mobile plus simple.
Mais encore une fois, il aurait probablement été préférable d'avoir une approche mobile propre sur Sponza pour atteindre 30 ips + sur de nombreux appareils mobiles, puis d'améliorer la scène pour les mobiles et les ordinateurs de bureau haut de gamme. Pourtant, la plupart des commentaires que nous avons reçus jusqu'à présent sur Twitter semblent indiquer que le résultat final fonctionne très bien sur la plupart des appareils. Certes, Sponza a été optimisé sur un GPU HD4000 (Intel Core i5 intégré) qui est plus ou moins équivalent aux GPU actuels des mobiles haut de gamme.
Nous étions assez satisfaits de la performance que nous avons réussi à réaliser. Sponza utilise notre shader avec ambient , diffuse , bump , specular et reflection activés. Nous avons des particules pour simuler de petits incendies à chaque coin, des os animés pour les drapeaux rouges, des sons positionnés en 3D et des collisions lorsque vous vous déplacez en utilisant le mode interactif.
Techniquement parlant, nous avons 98 meshes utilisés dans la scène , générant jusqu'à 377781 sommets, 16 bones actifs, plus de 60 particules pouvant générer jusqu'à 36 draw calls. Qu'avons-nous appris ? Une chose est sûre : avoir moins d'appels nuls est la clé d'une performance optimale, encore plus sur le web.
Le chargeur
Pour Sponza, nous voulions créer un nouveau chargeur, différent de celui par défaut que nous utilisons sur le site Web BabylonJS, pour avoir une application Web propre et soignée. J'ai alors demandé à Michel de proposer quelque chose de nouveau.
Il m'a d'abord envoyé l'écran suivant :

En effet, l'écran est très beau lorsque vous y jetez un coup d'œil pour la première fois. Mais alors vous pourriez commencer à vous demander comment vous allez le faire fonctionner sur tous les appareils, d'une manière vraiment réactive ? Essayons de comprendre.
Parlons d'abord du contexte. L'effet flou créé par Michel était agréable mais ne fonctionnait pas bien sur toutes les tailles de fenêtre et toutes les résolutions, générant un peu de moiré. Je l'ai ensuite remplacé par une capture d'écran « classique » de la scène. Cependant, je voulais que l'arrière-plan remplisse complètement l'écran sans barres noires et sans étirer l'image pour casser le ratio.
La solution vient principalement du CSS background-size: cover
+ centrage de l'image sur les axes X et Y. Du coup, on a alors l'expérience que je recherchais, quel que soit le ratio d'écran utilisé :

Les autres parties utilisent le bon vieux positionnement CSS basé sur le pourcentage. D'accord, avec cela trié, comment gérons-nous la typographie - la taille de la police doit être basée sur la taille de la fenêtre d'affichage. Évidemment, nous pouvons utiliser des unités de fenêtre pour cela. vw
et vh
(où 1vw correspond à 1 % de la largeur de la fenêtre d'affichage et 1vh correspond à 1 % de la hauteur de la fenêtre d'affichage) sont assez bien pris en charge sur tous les navigateurs, en particulier dans tous les navigateurs compatibles WebGL. (Il y a aussi un article sur Viewport Sized Typography sur Smashing Magazine que je vous recommande fortement de lire.)
Enfin, nous jouons avec la propriété d' opacity
de l'image de fond pour la faire passer de 0
à 1
en fonction du processus de téléchargement en cours passant de 0 à 100 %.
Oh, au fait, les animations de texte sont simplement réalisées à l'aide de transitions CSS ou d'animations combinées à une mise en page flexbox pour avoir un moyen simple mais efficace de s'afficher au centre ou à chaque coin.
Gérer toutes les entrées de manière transparente
Notre moteur WebGL fait tout le travail côté rendu pour afficher correctement les visuels sur toutes les plateformes. Mais comment garantir que l'utilisateur pourra se déplacer à l'intérieur de la scène quel que soit le type d'entrée utilisé ?
Dans la version précédente de Babylon.js, nous prenions en charge tous les types de saisie et d'interactions de l'utilisateur : clavier/souris, tactile, joysticks tactiles virtuels, manette de jeu, orientation de l'appareil VR (pour Card Board) et WebVR, chacun via une caméra dédiée. Vous pouvez lire notre documentation pour en savoir un peu plus à leur sujet.
Le toucher est géré de manière universelle avec la spécification Pointer Events propagée à toutes les plates-formes via le polyfill jQuery PEP (générant des événements tactiles pour l'application si nécessaire). Pour en savoir plus sur les événements de pointeur, vous pouvez lire sur Unifier le toucher et la souris : comment les événements de pointeur faciliteront la prise en charge du toucher entre navigateurs
Revenons à la démo alors. L'idée pour Sponza était d'avoir une caméra unique, gérant tous les scénarios d'utilisateurs à la fois : ordinateur de bureau, mobile et console.
Nous avons fini par créer UniversalCamera . Pour être honnête, c'était tellement évident et simple à créer que je ne sais toujours pas pourquoi nous ne l'avons pas fait avant. L'UniversalCamera est plus ou moins une caméra gamepad prolongeant la TouchCamera qui prolonge la FreeCamera .
La FreeCamera fournit la logique clavier/souris ; la TouchCamera fournit la logique tactile et la dernière extension fournit la logique de la manette de jeu.
UniversalCamera est maintenant utilisé par défaut dans Babylon.js. Si vous parcourez les démos, vous pouvez vous déplacer dans les scènes à l'aide de la souris, du toucher et de la manette de jeu sur chacune d'elles. Encore une fois, vous pouvez étudier le code pour voir exactement comment c'est fait.
Synchroniser les transitions avec la musique
Maintenant, cette partie est celle où nous nous sommes posé le plus de questions. Vous avez peut-être remarqué que la séquence d'introduction est synchronisée avec des zones spécifiques de la piste de lecture musicale . Les premières lignes s'affichent lorsque certains des tambours entrent en jeu, et la séquence de fin finale passe rapidement d'une caméra à l'autre sur chaque note de l'instrument à cor que nous utilisons.
Synchroniser l'audio avec la boucle de rendu WebGL n'est pas facile. Encore une fois, c'est la nature mono-thread de JavaScript qui génère cette complexité. Les articles sur Introduction aux HTML5 Web Workers : l'approche JavaScript multithreading partagent quelques idées derrière cela. Il est vraiment important de comprendre le problème pour comprendre le problème mondial auquel nous sommes confrontés, mais entrer dans les détails ici n'entre pas dans le cadre de cet article.
Habituellement, dans les scènes de démonstration (et les jeux vidéo), si vous souhaitez synchroniser les visuels avec les sons/la musique, vous allez être piloté par la pile audio. Deux approches sont souvent utilisées :
- Générer des métadonnées qui seraient injectées dans les fichiers audio, et qui pourraient ensuite "appeler" certains événements lorsque vous atteignez une partie spécifique de celui-ci,
- Analyse en temps réel du flux audio via FFT ou des technologies similaires pour détecter des pics intéressants ou des changements de BPM qui généreraient à nouveau des événements pour le moteur visuel.
Ces approches fonctionnent particulièrement bien dans des environnements multithreads comme C++. Mais en JavaScript, avec Web Audio, nous avons deux problèmes :
- JavaScript, qui est mono-thread et, malheureusement, la plupart du temps, les web workers ne nous aideront pas vraiment,
- Web Audio n'a aucun événement qui pourrait être renvoyé au thread d'interface utilisateur même si Web Audio est géré sur un thread séparé par le navigateur.
Web Audio a une minuterie beaucoup plus précise que JavaScript. Il aurait été fantastique de pouvoir utiliser ce minuteur séparé sur un thread séparé pour renvoyer les événements au thread d'interface utilisateur. Mais aujourd'hui, vous ne pouvez pas le faire (encore ?).
De l'autre côté, nous rendons la scène en utilisant WebGL et la méthode requestAnimationFrame
. Cela signifie que, dans les "meilleurs cas", nous avons une fenêtre de temps de 16 ms. S'il vous en manque une, il faudra attendre jusqu'à 16 ms pour pouvoir agir sur la trame suivante pour refléter la synchronisation du son (par exemple pour lancer un effet « fondu au noir »).
Je pensais alors injecter la logique de synchronisation dans la boucle requestAnimationFrame
. J'ai étudié le temps passé depuis le début de la séquence et me suis penché sur la possibilité d'ajuster le visuel pour réagir sur un événement audio. La bonne nouvelle est que l'audio Web restituera le son quoi qu'il se passe dans le fil principal de l'interface utilisateur. Par exemple, vous pouvez être sûr que l'horodatage de 12 secondes de la musique arrivera exactement 12 secondes après le début de la lecture de la musique, même si le GPU a du mal à restituer la scène.
Au final, nous avons finalement choisi la solution probablement la plus simple : utiliser les appels setTimeout()
! Oui je sais. Si vous examinez la plupart des articles, y compris celui que j'ai lié ci-dessus, vous découvrirez qu'il n'est pas du tout fiable. Mais dans notre cas, une fois la scène prête à être rendue, nous savons que nous avons téléchargé toutes nos ressources (textures et sons) et compilé nos shaders. Nous ne devrions pas être trop ennuyés par des événements inattendus saturant le fil d'interface utilisateur. GC pourrait être un problème mais nous avons aussi passé beaucoup de temps à le combattre dans le moteur : Réduire la pression sur le ramasse-miettes en utilisant la barre de développement F12 d'Internet Explorer 11.
Pourtant, nous savons que cette solution est loin d'être idéale. Passer à un autre onglet ou verrouiller votre téléphone et le déverrouiller quelques secondes plus tard pourrait générer quelques problèmes sur la partie synchronisation de la démo. Nous pourrions résoudre ces problèmes en utilisant l'API Page Visibility, par exemple en mettant en pause la boucle de rendu, divers sons et en recalculant les prochains délais pour les appels setTimeout()
.
Mais peut-être avons-nous manqué quelque chose ; peut-être, et même probablement, il y avait une meilleure approche pour gérer ce problème. Nous aimerions entendre vos réflexions et suggestions dans la section des commentaires si vous pensez qu'il existe une meilleure façon de résoudre le même problème.
Gestion de l'audio Web sur iOS
Le dernier défi que j'aimerais partager avec vous est la façon dont le Web Audio est géré par iOS sur iPhone et iPad. Si vous cherchez des articles sur "web audio + iOS", vous trouverez de nombreuses personnes ayant du mal à jouer des sons sur iOS. Maintenant, qu'est-ce qui se passe là-bas?
iOS a un support remarquable de Web Audio - même le mode audio binaural. Mais Apple a décidé qu'une page Web ne peut pas jouer de son par défaut sans l'interaction d'un utilisateur spécifique. Cette décision a probablement été prise pour éviter que de la publicité ou quoi que ce soit d'autre ne dérange l'utilisateur en diffusant des sons non sollicités.
Qu'est-ce que cela signifie pour les développeurs Web ? Eh bien, vous devez d'abord déverrouiller le contexte audio Web d'iOS après le toucher d'un utilisateur - avant d'essayer de jouer un son. Sinon, votre application Web restera désespérément muette.
Malheureusement, le seul moyen que j'ai trouvé pour effectuer cette vérification est d'adopter une approche de reniflage de la plate-forme utilisateur, car je n'ai pas trouvé de moyen de détection de fonctionnalités pour le faire. Ce n'est rien de moins qu'une technique horrible et pas à l'épreuve des balles, mais je n'ai trouvé aucune autre solution qui résoudrait le problème. Le code? Voici!
Si vous n'êtes pas sur iPad/iPhone/iPod, le contexte audio est immédiatement disponible. Sinon, nous déverrouillons le contexte audio d'iOS en jouant un son vide généré par le code sur l'événement touchend . Vous pouvez vous inscrire à l'événement onAudioUnlocked si vous souhaitez l'attendre avant de lancer votre jeu. Donc si vous lancez Sponza sur un iPhone/iPad, vous aurez cet écran final à la fin de la séquence de chargement :

Toucher n'importe où sur l'écran déverrouillera la pile audio d'iOS et lancera le "show".
Alors on y va ! J'espère que vous avez apprécié quelques idées derrière le développement de la démo. Pour en savoir plus, lisez le code source complet de cette démo sur notre GitHub. Évidemment, tout est open source, et vous pouvez retrouver les principaux fichiers sur GitHub : index.js et babylon.demo.ts.
Enfin, j'espère vraiment que vous serez maintenant encore plus convaincu que le Web est définitivement une excellente plate-forme pour les jeux ! Restez à l'écoute, car nous travaillons sur de nouvelles démos en ce moment même, et j'espère qu'elles seront également assez impressionnantes.
Cet article fait partie de la série de développement Web des évangélistes et ingénieurs techniques de Microsoft sur l'apprentissage pratique de JavaScript, les projets open source et les meilleures pratiques d'interopérabilité, y compris le navigateur Microsoft Edge.Nous vous encourageons à tester sur tous les navigateurs et appareils, y compris Microsoft Edge - le navigateur par défaut pour Windows 10 - avec des outils gratuits sur dev.microsoftedge.com, y compris les outils de développement F12 - sept outils distincts et entièrement documentés pour vous aider à déboguer, tester et accélérer vos pages Web. Visitez également le blog Edge pour rester à jour et informé des développeurs et experts Microsoft.