Platform logo

JetBrains Platform

Plugin and extension development for JetBrains products.

Ecosystem Engineering IntelliJ IDEA IntelliJ Platform Remote Development WebStorm

L’évolution de la prise en charge de WSL dans les JetBrains IDEs

Read this post in other languages:

Les JetBrains IDEs prennent en charge WSL depuis de nombreuses années. Au fil du temps, plusieurs méthodes d’utilisation de WSL ont toutefois été développées au sein de nos produits. En fonction du point d’entrée, l’IDE pouvait s’appuyer sur une architecture sous-jacente différente, ce qui se traduisait par une expérience différente.

À partir de la version 2026.2, nous ne recommandons désormais plus qu’un seul point d’entrée. Dans IntelliJ IDEA, WebStorm et PhpStorm, l’ouverture d’un projet situé dans WSL lance l’IDE dans ce que nous appelons le mode Native. L’IDE reste une application Windows, tandis qu’un petit agent exécuté dans WSL gère les fichiers et les processus pour son compte.

Dans cet article, nous allons expliquer comment fonctionne le mode Native, l’évolution de notre approche de l’intégration WSL qui y a mené et, puisque nous avons d’abord essayé trois autres approches, les raisons pour lesquelles nous pensons qu’il s’agit de la meilleure base pour votre environnement de développement.

Ce qu’implique la prise en charge de WSL dans un IDE

Nous allons commencer par une situation idéale où l’IDE fonctionne de manière fluide au sein de WSL tout en étant piloté depuis Windows. Concrètement, « de manière fluide » signifie que vous pouvez utiliser toutes les fonctionnalités de l’IDE (terminal, configurations d’exécution et de débogage, profilage, etc.) sur un projet situé dans un environnement Linux. Mieux encore, tout cela doit s’effectuer avec une latence minimale pour offrir une expérience de programmation rapide et naturelle, comme si les fichiers du projet et l’IDE lui-même se trouvaient dans un seul et même environnement système.

Nous allons retracer la façon dont nous avons relevé ce défi, en commençant par la toute première implémentation, dans laquelle l’IDE interagissait avec WSL à l’aide du protocole de transport 9P. Nous parlerons ensuite du développement à distance et de WSLg, avant d’examiner le mode Native :le mode de prédilection actuellement pour le fonctionnement des IDE avec WSL.

Vers une exécution native de l’IDE dans WSL

Accès au système de fichiers via 9P et GeneralCommandLine

Pour fonctionner, l’IDE doit pouvoir accéder aux éléments de base d’un projet : ses fichiers. C’est là qu’intervient le protocole de système de fichiers 9P. Il fournit le mécanisme permettant aux processus Windows d’accéder aux fichiers dans WSL. En pratique, les opérations I/O sur les fichiers du projet effectuées par l’IDE (scan, indexation, accès aux archives, et autres opérations similaires) sont routées vers la machine virtuelle Linux via la couche du système de fichiers basée sur 9P.

Une fois que la question de l’accès aux fichiers est réglée, le défi suivant concerne l’exécution des processus. Au cours de son exécution sous Windows, l’IDE doit pouvoir appeler des outils au sein de WSL avec les chemins d’accès, répertoires de travail, exécutables, variables d’environnement et arguments Linux corrects. La classe GeneralCommandLine, interne à l’IDE, gère cela en normalisant l’exécution des commandes dans l’environnement WSL.

Bien que cette architecture permette à l’IDE de fonctionner avec WSL, elle impose des compromis importants en matière d’accès aux fichiers et d’exécution des processus.

Le protocole 9P est réputé problématique pour plusieurs raisons :

  • Prise en charge limitée des liens symboliques : 9P n’expose pas correctement les liens symboliques Linux à Windows via \wsl$. Il est donc possible que l’IDE détecte une entrée sans pour autant pouvoir résoudre ou indexer l’arborescence de répertoires associée. Cela concerne les espaces de travail pnpm, les environnements virtuels Python, les dépôts de type path de PHP Composer, ainsi que d’autres environnements qui utilisent des liens symboliques.
  • Analyses Microsoft Defender : une analyse ponctuelle via 9P peut allonger les lectures de fichiers WSL de plusieurs dizaines de secondes.
  • Latence et débit réduits : l’accès au système de fichiers via 9P ajoute de la latence et peut entraîner une baisse significative du débit, en particulier dans les workflows impliquant un grand nombre de petits fichiers. Les opérations essentielles de l’IDE, comme l’indexation, sont particulièrement concernées, car elles génèrent un grand nombre de requêtes distinctes qui doivent transiter entre Windows et la machine virtuelle WSL via 9P.

La situation n’était pas moins compliquée du côté de GeneralCommandLine. Ce pipeline complexifiait la maintenance, car les développeurs devaient prendre en compte les spécificités sémantiques liées à l’exécution sous WSL dans l’ensemble de la base de code.

Avec le temps, l’évolution et la maintenance de cette approche sont donc devenues de plus en plus complexes, tandis que des problèmes persistants liés aux liens symboliques et aux performances continuaient de se manifester.

Exécution de l’IDE dans WSL avec WSLg

Et si l’IDE lui-même résidait dans WSL, au plus près du projet sur lequel il travaille ? C’est là qu’intervient WSLg. Il offre un moyen d’exécuter des applications graphiques Linux dont le rendu visuel s’intègre directement au bureau Windows.

Voici les raisons pour lesquelles nous ne recommandons pas l’approche WSLg :

  • Du point de vue du produit, si l’IDE s’affiche sous Windows, il est préférable qu’il se comporte comme une véritable application Windows plutôt que comme une application graphique Linux projetée sur le bureau Windows. Cela préserve un meilleur contrôle sur l’expérience de l’IDE et évite de dépendre d’une couche supplémentaire pour utiliser l’interface graphique à distance.
  • Dans une configuration WSLg, l’IDE peut s’exécuter via le chemin Wayland natif : JetBrains Runtime utilise alors WLToolkit avec le serveur d’affichage Wayland de WSLg. Ce chemin comporte des limitations connues qui affectent le rendu, les fenêtres contextuelles, la gestion des fenêtres, les méthodes de saisie et l’intégration au bureau.

Cette configuration n’a jamais servi de base à une expérience produit de premier ordre. Bien qu’il soit techniquement possible d’exécuter l’IDE via WSLg, cette solution n’a jamais été considérée comme la méthode à privilégier, et aucun parcours d’installation ou d’intégration prêt à l’emploi n’a été proposé dans ce but. Cela reste une solution de contournement ponctuelle plutôt qu’un workflow d’IDE pris en charge.

L’approche du développement à distance

Le développement à distance abordait ces mêmes problématiques fondamentales d’accès aux fichiers et d’exécution des processus sous un autre angle. Plutôt que d’étendre l’IDE Windows au-delà de la frontière de WSL, cette approche déplaçait le backend de l’IDE dans WSL et ne conservait que le client côté Windows. Cette architecture résolvait plus directement les problèmes d’intégration sous-jacents, mais elle imposait son propre lot de compromis.

Le principal défi technique consistait à établir et maintenir la communication entre les deux parties, tout en veillant à ce que l’interface utilisateur reflète fidèlement les actions de l’utilisateur et que l’IDE continue de fonctionner comme un ensemble cohérent. En revanche, placer le backend dans WSL offre l’avantage indéniable d’un accès direct aux fichiers et aux processus Linux.

Dans cette configuration, les deux parties de l’IDE communiquent à l’aide du protocole JetBrains RD. Le protocole est un flux bidirectionnel structuré de modèles et d’événements de l’IDE qui synchronise logiquement le client léger et l’IDE en backend, tandis que toutes les tâches lourdes, telles que l’indexation, l’analyse, les builds, le débogage, les opérations VCS, etc., s’exécutent sur le backend.

Le client, lui :

  • Affiche toutes les fenêtres et tous les éditeurs, et gère les saisies de l’utilisateur.
  • Reflète l’état du projet et de l’éditeur reçu du backend via le protocole RD, et renvoie les modifications, les déplacements du curseur, les commandes de refactorisation, les actions de débogage, etc.
  • Charge les plugins au niveau de l’interface utilisateur.

Là où ça coince, c’est sur le coût de cette architecture divisée. Le backend de l’IDE est lui-même un composant assez lourd, qui nécessite environ 2 Go d’espace disque supplémentaire ainsi qu’un certain temps pour le télécharger et l’installer dans WSL. Cette séparation entraîne également une pénalité de performance intrinsèque : les états liés aux événements de l’interface, les saisies de l’utilisateur et les autres données d’interaction doivent constamment transiter entre le client local et le backend.

De plus, cela augmente le travail de développement, car le code doit être scindé en une partie client et une partie serveur. Le fait de ne pas séparer certains modules peut entraîner des ralentissements et des blocages dans les interfaces utilisateur particulièrement dynamiques. Le travail d’ingénierie associé devient donc un coût constant et inévitable.

Le mode Native et l’agent IJent

Le design actuel, désormais intégré dans la plupart de nos IDE, représente l’aboutissement de ce travail et corrige un grand nombre des lacunes des approches précédentes du WSL.

Pour fournir un accès au système de fichiers Linux, à ses processus et aux autres ressources de l’environnement sans dépendre de 9P, de GeneralCommandLine ou d’autres mécanismes de communication de second ordre, nous avons développé un petit agent nommé IJent. Comme il est conçu spécifiquement pour des scénarios d’IDE, nous pouvons façonner son comportement, son protocole et ses fonctionnalités selon nos besoins.

L’IDE et IJent forment ensemble un binôme client-serveur. Ce modèle peut rappeler celui du développement à distance, mais le composant serveur est ici beaucoup plus léger, et en même temps plus polyvalent. L’installation d’IJent dans un environnement WSL n’est que l’une des configurations possibles ; on peut également appliquer le même modèle à Docker et aux conteneurs de développement.

En choisissant cette pile technologique, nous répondons à de nombreuses problématiques :

  • Implémentation Rust : Rust permet de créer un exécutable léger. En évitant d’utiliser Java/Kotlin pour l’agent, nous éliminons les dépendances d’exécution supplémentaires à l’intérieur des conteneurs ou de WSL.
  • Couche de transport : Stdio nous offre un transport portable et compatible avec les pare-feu dans tous les environnements. Les sockets Hyper-V sur WSL fournissent un chemin plus rapide, particulièrement avantageux pour les transferts de fichiers volumineux ou nombreux.
  • Sémantique de système de fichiers correcte : IJent exécute les opérations sur le système de fichiers pour le compte de l’IDE au sein de l’environnement cible. Ainsi, la résolution des chemins, y compris les liens symboliques, suit la sémantique Linux correcte au lieu de passer par 9P. Les plugins tiers bénéficient également de ce modèle, puisque leurs opérations sur les fichiers sont routées via IJent.

EelApi : une seule interface pour tous les environnements

Pour que l’IDE tire pleinement parti d’IJent, des modifications sont également nécessaires côté IDE. Pour cela, nous avons EelApi.

EelApi est une API conçue pour s’affranchir de la distinction entre environnements locaux et distants, pour toute personne qui écrit du code lié à l’IDE : auteurs de plugins comme contributeurs à la plateforme. Avec EelApi, l’environnement sous-jacent avec lequel l’IDE interagit ne devrait plus avoir d’importance, ce qui supprime le besoin de gérer explicitement ces problématiques dans le code. En ce sens, EelApi est agnostique vis-à-vis de la plateforme, et l’IDE n’a pas besoin de savoir s’il travaille en local, dans WSL, dans Docker ou dans un conteneur de développement.

IJent implémente globalement l’interface d’EelApi pour fournir les fonctionnalités concrètes qu’EelApi expose à l’IDE et aux plugins.

Si vous souhaitez une explication plus détaillée sur EelApi, ainsi qu’une présentation pratique du sujet, consultez l’article The Dev Containers Story : Introducing EelApi for Plugin Authors (L’histoire des conteneurs de développement : présentation d’EelApi à l’intention des auteurs de plugins).

Ce que cela implique en pratique

Il existe aujourd’hui deux moyens d’ouvrir un projet WSL :

  • Ouvrir le projet directement vous donne accès au mode Native dans IntelliJ IDEA, WebStorm et PhpStorm, et d’autres IDE sont en train d’adopter l’architecture IJent et EelApi.
  • Le point d’entrée Remote Development de l’écran d’accueil fonctionne toujours, mais n’est plus la façon recommandée d’ouvrir un projet WSL.

Nous avons réalisé des tests de performance afin de comparer le mode 9P et le mode Native. Les résultats montrent un gain de performances assez net en faveur de la nouvelle approche :

Benchmark d’ouverture à froid

IJent réduit le temps d’attente de 38 % pour un projet WSL volumineux

9P IJent
Prêts à l’emploi
18.5 s
11.5 s

38 % de moins

Scanner l’arborescence du projet
8.1 s
3.7 s

54 % de moins

Indexer les fichiers
10.8 s
8.4 s

22 % de moins

Lire le contenu des fichiers
12.2 s
5.7 s

53 % de moins

Contexte utilisé : une première ouverture à froid du spring-framework, avec 23 sous-projets et 8 191 fichiers sources. Aucune différence mesurable n’a été constatée sur un petit projet comportant peu de fichiers sources./p>

Configuration de test : médiane de cinq exécutions mesurées sur Windows 11 avec WSL 2, Ubuntu 24.04 et IntelliJ IDEA Ultimate 263.SNAPSHOT.

Au-delà des performances, cette architecture inscrit le développement dans WSL dans le contexte plus large du développement dans des environnements non locaux, ce qui permet de réutiliser le même modèle sous-jacent.

Merci de nous avoir lus, et merci pour tous vos retours qui nous ont permis d’en arriver là. Dites-nous en commentaire ce que vous pensez du mode Native dans vos projets.

Auteur de l’article original en anglais :

Kristina Pchelintseva

Kristina Pchelintseva