跳转至正文

在 Windows 上用 WSL2 开发 Capacitor

在 WSL2 中运行 Capacitor Web 工具链,同时把 Android 模拟器和设备留在 Windows 上:adb 桥接、镜像网络、文件系统性能、live reload,以及用 Capgo Build 构建 iOS。

在 Windows 上用 WSL2 开发 Capacitor

WSL2 为 Windows 开发者提供了真正的 Linux shell,当团队的脚本、Dockerfile 和 CI 都默认用 bash 时,这一点很重要。对 Capacitor 来说,这套方案很好用,但有一个原则:把 web 工具链放在 WSL2,把 Android 模拟器、USB 设备和 Android Studio 留在 Windows,然后用 adb 把两者桥接起来。

本指南会介绍这套配置、容易踩坑的网络细节,以及 iOS 如何通过 Capgo 构建.

何时值得使用 WSL2

在以下场景使用 WSL2:

  • 仓库包含在 PowerShell 中会报错的 bash 脚本、Makefile 或 Husky hooks。
  • 需要在本地和 CI 环境中运行相同的 Docker 镜像。
  • 希望使用 Linux node_modules 文件布局,使 lockfiles 与 Linux CI 环境保持一致。

如果只需要 Android Studio 和终端,则无需使用 WSL2。在这种情况下, 原生 Windows 指南 会更加简单。

1) 安装 WSL2 及发行版

以管理员身份运行 PowerShell:

wsl --install -d Ubuntu

重启,打开 Ubuntu,创建你的 Linux 用户。更新并安装基础工具:

sudo apt update && sudo apt install -y build-essential unzip openjdk-21-jdk
curl -fsSL https://bun.sh/install | bash

2) 把项目放在 Linux 文件系统中

在 Linux home 目录下创建项目,而不是在 /mnt/c:

mkdir -p ~/dev && cd ~/dev
bun create vite@latest my-app
cd my-app
bun install

用 Windows 工具访问这些文件,可以通过 \\wsl$\Ubuntu\home\you\dev\my-app. 装了 WSL 扩展的 VS Code 可以直接通过 code ..

为什么这很重要:通过 /mnt/c 的跨文件系统访问,对于以下目录中成千上万个小文件来说很慢: node_modules,而且 Vite 使用的 inotify 监听器无法可靠地监听 Windows 驱动器上的文件变化。

3) 确定 Android SDK 的存放位置

两种可行的方案:

方案 A(推荐):SDK 在 Windows 上,WSL2 中的 Gradle 指向 Linux 上的 SDK 副本。 在 Windows 上安装 Android Studio 以使用模拟器和 GUI 工具,并在 WSL2 里另外安装一套命令行 SDK 供 Gradle 使用:

mkdir -p ~/Android/Sdk/cmdline-tools && cd ~/Android/Sdk/cmdline-tools
# download commandlinetools-linux-*.zip from the Android developer site
unzip commandlinetools-linux-*.zip && mv cmdline-tools latest
echo 'export ANDROID_HOME=$HOME/Android/Sdk' >> ~/.bashrc
echo 'export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools' >> ~/.bashrc
source ~/.bashrc
sdkmanager "platform-tools" "platforms;android-36" "build-tools;36.0.0"
sdkmanager --licenses

是的,这会多复制几百 MB 的数据。作为交换,Gradle 以 Linux 速度运行,而且完全不会触碰 /mnt/c.

方案 B:所有内容都放在 Windows 上,WSL2 只用于 Web 构建。 你在 bun run build WSL2 中运行,并 cap sync 加 gradlew 通过 PowerShell 对同一批文件执行 \\wsl$。这种方式可行,但速度更慢,而且混用了两种 shell。只有在 WSL2 中无法安装任何东西时才选它。

本指南其余部分均假设采用方案 A。

4) 在 WSL2 与 Windows 之间桥接 adb

模拟器和 USB 手机连接在 Windows 上。WSL2 中的 Gradle 构建和 cap run android 需要访问它们。在 Windows 上只保留一个 adb server,并让 WSL2 作为客户端。

在 Windows 上,启动监听所有接口的 adb server。使用 Windows SDK 中的 adb:

adb kill-server
adb -a -P 5037 nodaemon server

让该窗口保持打开。如果弹出提示,请允许 5037 端口通过 Windows 防火墙供 WSL 虚拟适配器使用。

在 WSL2 中,将 adb 客户端指向 Windows 宿主机:

export WSL_HOST=$(ip route show default | awk '{print $3}')
export ADB_SERVER_SOCKET=tcp:$WSL_HOST:5037
adb devices

现在模拟器或手机会出现在 WSL2 中。两个 adb 二进制文件的主版本必须一致,因此请同时 platform-tools 更新两端。

镜像网络可简化此过程

在 Windows 11 22H2 或更高版本上,启用镜像网络,让 WSL2 共享 Windows 网络栈。创建或编辑 %USERPROFILE%\.wslconfig:

[wsl2]
networkingMode=mirrored

运行 wsl --shutdown,重新打开 Ubuntu,然后使用 ADB_SERVER_SOCKET=tcp:127.0.0.1:5037。宿主机 IP 不再每次重启都变化,live reload 也更简单了。

备选方案:将 USB 设备直通到 WSL2

如果想让 adb 完全在 WSL2 里连接真机,请使用 usbipd-win:

winget install usbipd
usbipd list
usbipd bind --busid 2-3
usbipd attach --wsl --busid 2-3

然后添加来自以下位置的 udev 规则: Linux 指南 在 WSL2 内部。但这对于模拟器没有帮助,模拟器仍需网络连接。

5) 运行 App

通过 adb 桥接后,Capacitor 的表现与 Linux 一致:

bun add @capacitor/core @capacitor/android @capacitor/ios
bun add -d @capacitor/cli
bunx cap init
bun run build
bunx cap add android
bunx cap add ios
bunx cap run android

cap open android 要求在同一台机器上安装 Android Studio。相反,请在 Windows 中通过 android/ 在 Windows Android Studio 中打开 \\wsl$\Ubuntu\home\you\dev\my-app\android文件夹。Studio 自带的 Gradle 会在 Windows 上进行构建,而你的终端在 WSL2 中构建;两者共享相同的源文件。

6) 跨边界的 Live reload

Vite 运行在 WSL2 中,App 运行在 Windows 模拟器或真机上。模拟器必须能够访问开发服务器。

启动绑定到所有接口的 Vite:

bun run dev -- --host 0.0.0.0

在 Capacitor 中将其指向 capacitor.config.ts:

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'my-app',
  webDir: 'dist',
  server: {
    url: 'http://10.0.2.2:5173',
    cleartext: true,
  },
};

10.0.2.2 是模拟器对宿主机的别名。通过镜像网络 (mirrored networking),WSL2 端口在 Windows 宿主机上可见,因此该地址可以访问 Vite。如果没有开启镜像网络,请先在 Windows 上进行端口转发:

netsh interface portproxy add v4tov4 listenport=5173 listenaddress=0.0.0.0 connectport=5173 connectaddress=$(wsl hostname -I)

若使用 USB 连接手机,请将 URL 替换为 Windows 的局域网 IP,并在 Windows 防火墙中允许 5173 端口。运行 bunx cap sync android 修改配置后,并移除 server 限制后再进行 release build。

7) 通过 WSL2 使用 Capgo 进行 iOS Build

Xcode 需要 macOS,因此 WSL2 可以处理到原生编译之前的所有工作,剩下的交给 Capgo:

bun run build
bunx cap sync ios
bunx @capgo/cli@latest login
bunx @capgo/cli@latest build init --platform ios
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release

通过 CLI 上传准备好的 ios/ 项目,并将日志流式传输回您的 WSL2 终端。无需 Mac 即可使用 OpenSSL 或 iOS 证书生成器生成签名材料。详情请参阅 使用 Capacitor 和 Capgo 进行 iOS Build,在 Linux 上构建 iOS 应用,这在 WSL2 中的操作完全一致。

8) 日常开发避免进行 Native Build

一旦两款应用都已上架应用商店, Capgo Live Updates 即可无需触碰 Gradle 或 Capgo Native Build,直接从 WSL2 推送 Web 端变更:

bunx @capgo/cli@latest bundle upload --channel production

常见的 WSL2 问题

  • adb: device offline 或 WSL2 中的空列表:Windows adb server 未运行或 -a,或者版本不一致。请重启并对比 adb version 两端的版本。
  • 重启后 Host IP 发生变化:在未开启镜像网络(mirrored networking)时这是正常现象。请将 WSL_HOST export 放入 ~/.bashrc 中以便重新计算,或者切换到镜像模式。
  • Vite 无法检测到文件变更:项目位于 /mnt/c。请将其移动到 Linux home 目录下。
  • Gradle 运行极其缓慢:原因相同,或者 Gradle 缓存位于 /mnt/c。请将 ~/.gradle 保留在 WSL2 中。
  • 时钟偏移导致 Apple API 认证失败 build init:WSL2 在休眠后会出现时钟偏移。请运行 sudo hwclock -s 并重试。
  • cap open android 失败时触发:Studio 运行在 Windows 上。请直接从 Studio 中打开该文件夹。

总结

如果你的团队习惯使用 bash,那么 WSL2 是 Capacitor Web 工具链的理想环境。你可以将模拟器和设备保留在 Windows 上,通过单个 adb server 进行桥接,将文件存放在 Linux 文件系统中,并让 Capgo Build 负责 iOS 编译。最终,你可以在 Windows 笔记本上实现 Linux 工作流,同时依然能向两大应用商店发布应用。

为 Capacitor 应用提供 Live Updates

当 Web 层出现线上 Bug 时,通过 Capgo 发布修复,而不用等 App Store 审核好几天。用户会在后台收到更新,原生变更则仍走正常审核流程。

博客最新动态

Capgo 为你提供打造真正专业的移动应用所需的最有价值的洞察。