JetBrains IDE 对 WSL 支持的演进
JetBrains IDE 与 WSL 协作已有多年,随着时间推移,我们各产品中涌现出多种使用 WSL 的方式。根据入口不同,IDE 可能依赖不同的底层架构,从而带来不同的体验。
自 2026.2 版本起,我们推荐统一使用单一入口。在 IntelliJ IDEA、WebStorm 和 PhpStorm 中,打开位于 WSL 中的项目时,IDE 会以我们所说的 *Native(原生)*模式运行。IDE 仍然是 Windows 应用程序,而 WSL 内部的一个小型代理会代其处理文件和进程。
下面介绍 Native 模式的工作原理、我们处理 WSL 集成的方案是如何演进的,以及——因为我们首先尝试了另外三种方案——为什么我们确信它是您工作的正确基础。
在 IDE 中支持 WSL 需要什么
我们先从一个人性化图景说起:IDE 在 WSL 内部无缝运行,同时用户从 Windows 操作。实际上,“无缝”意味着您可以使用 IDE 的任何功能——终端、运行和调试配置、性能分析等——来处理位于 Linux 环境中的项目。不仅如此,这还必须尽可能降低延迟,让编码体验快速而自然,仿佛项目文件和 IDE 本身处于同一个操作系统环境中。
[LOADING...]
我们将追溯这一挑战从最初实现开始的解决历程。最初的实现中,IDE 通过 9P 传输协议与 WSL 交互;随后我们会介绍 Remote Development 和 WSLg,最后再考察 Native 模式——也就是当前 IDE 与 WSL 协作的首选方式。
迈向 WSL 中的原生 IDE 执行
9P 文件系统访问与进程执行
为了使 IDE 能够运行,它需要访问项目的基础内容,也就是普通文件。这正是 9P 文件系统协议的用武之地。它提供了一种机制,让 Windows 侧的进程能够访问 WSL 内的文件。实际上,IDE 执行的项目相关文件 I/O——扫描、索引、压缩包访问等——都会经过基于 9P 的文件系统层路由到 Linux 虚拟机。
[LOADING...]
文件访问问题解决后,下一个挑战是进程执行。IDE 在 Windows 上运行时,必须能够在 WSL 内以正确的 Linux 路径、工作目录、可执行文件、环境变量和参数调用工具。IDE 内部的 GeneralCommandLine 类通过规范化 WSL 环境中的命令执行来管理这一点。
尽管这种架构让 IDE 能够对 WSL 进行操作,但也给文件访问和进程执行都引入了显著的权衡取舍。
9P 协议存在以下众所周知的问题:
- 符号链接处理能力有限——9P 无法通过
\\wsl$向 Windows 正确暴露 Linux 符号链接。因此,IDE 可能检测到某个条目,却无法解析或索引所链接的目录树。这会影响 pnpm workspaces、Python 虚拟环境、PHP Composer 路径仓库,以及其他依赖符号链接的环境。 - Microsoft Defender 扫描——通过 9P 进行访问时扫描可能让 WSL 文件读取延迟数十秒。
- 延迟与吞吐量下降——基于 9P 的文件系统访问会带来延迟,吞吐量也可能显著下降,尤其是在涉及大量小文件的工作流中。索引等核心 IDE 操作正是这种模式:会产生大量独立请求,通过 9P 跨越 Windows/WSL 虚拟机边界。
在 GeneralCommandLine 一侧,情况同样不容乐观。这条管道增加了维护负担,因为开发人员不得不在整个代码库中考虑 WSL 特有的执行语义。
因此,这种方法越来越难以扩展和维护,并持续暴露出符号链接处理和性能方面的问题。
使用 WSLg 在 WSL 内运行 IDE
换一种思路:如果 IDE 本身位于 WSL 内、贴近它要处理的项目,会怎样?这正是 WSLg 的用武之地。它提供了一种运行 Linux GUI 应用程序的方式,这些应用的视觉输出会直接集成到 Windows 桌面中。
[LOADING...]
以下是我们不推荐 WSLg 方案的原因:
- 从产品角度看,如果 IDE 显示在 Windows 上,最好让它表现为 Windows 原生应用,而不是投射到 Windows 桌面的 Linux GUI 应用。这样可以保留对 IDE 体验的更强控制,并避免依赖额外的 GUI 远程层。
- 在 WSLg 设置中,IDE 可能运行在原生 Wayland 路径上,JetBrains Runtime 会通过 WLToolkit 与 WSLg 的 Wayland 合成器交互。这条路径在渲染、弹窗、窗口管理、输入法和桌面集成方面存在已知限制。
这种设置从未构建出一流的产品体验。虽然通过 WSLg 运行 IDE 在技术上可行,但它从未被视为首选方向,也没有提供专门的即开即用安装或上手流程。它仍然是一种临时替代方法,而不是受支持的 IDE 工作流。
Remote Development 方案
另一种方案是 Remote Development。它从不同角度解决了文件访问和进程执行这两项基本挑战。它不是扩展基于 Windows 的 IDE 以跨越 WSL 边界,而是将 IDE 后端移入 WSL,仅在 Windows 上保留客户端。这种架构更直接地解决了底层集成问题,但也带来了另一组权衡取舍。
[LOADING...]
这种配置的主要技术挑战,是在二者之间建立并维持通信,同时确保 UI 准确反映用户操作,且 IDE 作为连贯整体继续运行。与此同时,将后端放在 WSL 内也具有明显优势:可以直接访问 Linux 文件和进程。
在这种设置中,IDE 的两个部分通过 JetBrains RD 协议进行通信。该协议是 IDE 模型和事件的结构化双向流,使瘦客户端与后端 IDE 在逻辑上保持同步,而索引、分析、构建、调试、VCS 操作等所有繁重工作都在后端完成。
客户端则负责:
- 渲染所有窗口和编辑器,并处理用户输入。
- 镜像通过 RD 协议从后端接收到的项目和编辑器状态,并回传编辑操作、光标移动、重构命令、调试操作等。
- 加载 UI 层插件。
然而,无法回避的问题是这种分离架构的成本。IDE 后端本身就是重量级组件,需要约 2 GB 的额外磁盘空间,并需要在 WSL 内花时间下载和安装。这种拆分也会带来固有的性能损失,因为 UI 事件状态、用户输入和其他交互数据必须持续在本地客户端与后端之间传输。
它同样增加了开发开销,因为代码必须拆分为客户端与服务端部分。如果特定模块没有拆分,高度动态的 UI 可能会出现延迟和卡顿。因此,相关工程成本成了一种持续且不可避免的负担。
Native 模式与 IJent 代理
当前的设计——现已集成到我们大多数 IDE 中——代表了这项工作的最终成果,并解决了早期 WSL 方案中的许多缺陷。
[LOADING...]
为了在不依赖 9P、GeneralCommandLine 或其他二等通信机制的情况下提供对 Linux 文件系统、进程和其他环境资源的访问,我们开发了一个名为 IJent 的小型代理。由于它是专门为 IDE 场景设计的,我们可以根据自己的需求塑造其行为、协议和能力。
IDE 与 IJent 共同构成一对客户端—服务端。这可能看起来类似于 Remote Development 模型,但服务端组件要精简得多,同时也更通用。将 IJent 安装到 WSL 环境只是多种可能配置之一;同一模型也可以应用于 Docker 和 Dev Containers。
通过选择这一特定的技术栈,我们解决了广泛的问题:
- Rust 实现——Rust 让可执行文件保持精简。代理不采用 Java/Kotlin,因此我们消除了容器或 WSL 内额外的运行时依赖。
- 传输层——Stdio 提供了一种跨所有环境可移植、防火墙友好的传输方式。WSL 上的 Hyper-V sockets 则提供了更快的路径,尤其有利于大型或大量文件系统传输。
- 正确的文件系统语义——IJent 代表 IDE 在目标环境中执行文件系统操作。因此,路径解析(包括符号链接)遵循正确的 Linux 语义,而不是经由 9P 中转。第三方插件也能受益于这种模型,因为它们的文件操作同样会通过 IJent 路由。
EelApi:适用于任何环境的统一接口
为了让 IDE 从 IJent 中充分受益,IDE 侧也需要做出改变。这就是 EelApi 的由来。
EelApi 是一个 API,旨在为所有编写 IDE 相关代码的人(无论是插件作者还是平台贡献者)抽象本地环境与远程环境之间的差异。借助 EelApi,IDE 所运行的底层环境不再重要,无需在代码中显式处理这些差异。从这个意义上说,EelApi 是与平台无关的,IDE 不需要知道自己是在本地、WSL、Docker 还是 Dev Container 中工作。
一般来说,IJent 实现了 EelApi 接口,提供 EelApi 向 IDE 和插件暴露的实际功能。
如果您想了解更详细的 EelApi 说明及实际介绍,请参阅文章 The Dev Containers Story: Introducing EelApi for Plugin Authors。
这在实践中意味着什么
目前有两种打开 WSL 项目的方式:
- 直接打开项目,您可以进入 IntelliJ IDEA、WebStorm 和 PhpStorm 中的 Native 模式;与此同时,更多 IDE 正在采用 IJent 和 EelApi 架构。
- 欢迎屏幕上的 Remote Development 入口仍然可用,但不再是打开 WSL 项目的推荐方式。
我们进行了性能测试,以比较 9P 模式和 Native 模式。结果显示新方案具有明显的性能优势:
冷打开基准测试
适用范围: 冷首次打开 spring-framework,包含 23 个子项目和 8,191 个源文件。源文件较少的小项目未显示出可测差异。
测试环境: 在 Windows 11 + WSL 2、Ubuntu 24.04 和 IntelliJ IDEA Ultimate 263.SNAPSHOT 上各测量五次的中间值。
除了性能之外,这种架构还将 WSL 开发置于非本地环境开发的更广泛背景下,使它们可以通过同一个底层模型进行处理。同一个 IJent 代理已经在支持我们在 Docker 和 Dev Containers 方面的工作。
感谢您的阅读,也感谢所有帮助我们走到这一步的反馈。欢迎在评论区告诉我们 Native 模式在您的项目上表现如何。