Skip Navigation code drift

Running Expo in Windows Subsystem for Linux (WSL2)

written  &  updated
in Code, but also Expo, React Native, & Tools
🔁
This article was written for the Expo Blog and appeared with the title Running Expo in Windows Subsystem for Linux (WSL2). It's been reproduced here with permission.

If it runs in Node.js, it can run Expo. Even better, if it runs in Linux, you can take advantage of all the excellent React Native tools that may not be utilizing cross-platform utilities like cross-env. Since Windows 10 has support for Linux through a virtualized Windows Subsystem for Linux (WSL2), we can use that to run our Expo applications, build tooling, and more.

Getting everything working on WSL2 does have a few gotchas, which is why this guide can help you get up and running quickly and avoid some of the most common pitfalls (spoiler: it’s networking related).

Overview

  • Setting up WSL2
  • Configuring WSLHostPatcher
  • Alternative: Using Windows Firewall Rules
  • Final considerations

Setting up WSL2 for Expo Development

WSL2 gives you access to a fully featured Linux command line inside of Windows. While great cross-platform tools like env-cmd exist, not every tool we use in React Native development is Powershell-aware. Using WSL2 eliminates those problems entirely; it’s just Linux. Unless specified, all our commands will be in WSL2’s Linux environment.

What You’ll Need for This Step

  1. Windows 10 or 11 (with or without the Windows Insider Program)
  2. Windows Subsystem for Linux (Instructions here)

The first thing we’re going to need is both Expo CLI and EAS CLI in our WSL environment. From there, we can initialize our standard Expo app, just like a managed app. We’re using the Typescript template, but you can also opt for a vanilla JS experience.

$ npm install -g eas-cli
$ npm install -g expo-cli
$ expo init expo-cdc-example
$ cd expo-cdc-example
$ yarn start

We’ll get our Expo QR code, but when we try to visit our developer page, we’ll end up at a 404. This happens because to our browser, localhost is referring to Windows, and Windows doesn’t know that those Expo requests need to be forwarded along to the WSL.

Configuring WSLHostPatcher

Unless you have specific security concerns (such as exposing your Windows machine to the Internet), the fastest way to fix the port forwarding problems is with a utility called [WSLHostPatcher](https://github.com/CzBiX/WSLHostPatcher). Built on the Windows Detours framework, it dynamically updates the bind & listen addresses for your WSL instances. We’re going to download the utility and run it every time our WSL instances starts. (Adjust appropriately for a non-BASH environment)

$ cd
$ mkdir wsl; cd wsl
$ wget https://github.com/CzBiX/WSLHostPatcher/releases/download/v0.1.0/release.zip
$ unzip release.zip
# run WSLHostPatcher on every login
$ echo "./wsl/WSLHostPatcher.exe" >> ~/.bashrc

Let’s close our dev console, along with any running yarn instances, and reload WSL. We’ll be greeted with WSLHostPatcher confirming it found and updated our WSL instance.

Dll path: \\wsl$\Ubuntu\home\<yourname>\wsl\WSLHostPatch.dll
Found 1 WSL host
Patched 1

Give expo start a try now, and watch how your localhost request automatically finds its way to your Expo instance.

Alternative: Windows Firewall Setup

One of the downsides to WSLHostPatcher is that it will bind your WSL instance to 0.0.0.0. For most development scenarios, this is perfectly ok. If you have security concerns though, you can also use a Powershell script to forward specific ports to your WSL instance. This is a much longer setup, but uses the built-in Windows Firewall.

First, you’ll want to download the following script based on the excellent work of @edwindijas on github, and save it to c:\scripts\wslbridge.ps1. This script does a couple things.

  1. Removes all existing WSL2 based routing rules
  2. Creates new Outbound & Inbound rules on the Windows machine for your specified ports
  3. Removes any existing proxies between Windows and your WSL instance
  4. Creates a proxy from Windows to your WSL instance for all specified ports
# [Configuration]
# All the ports you want to forward separated by coma
$ports=@(7700,8088,8089,19000);

# You can change the addr to your ip
# config to listen to a specific address
$addr='0.0.0.0';

# [Init]
$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

$ports_a = $ports -join ",";

# Remove Firewall Exception Rules
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

# adding Exception Rules for inbound and outbound Rules
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";

iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
}

Open up Task Scheduler and set up a task that will run the script on login, after a small delay. For reference, your task should look like the following:

Create Task dialog box


Creating a task in the Task Scheduler

Task Triggers tab


Setting a Trigger condition for our task

The Actions tab


Task Action set to start the wslbridge.ps1 script with the -ExecutionPolicy Bypass flag, allowing it to run with the necessary permissions

Once configured, either on login or by running the script manually, Windows will automatically forward ports to WSL for you. From here, you can now run expo start from within WSL, and localhost will resolve as expected.

Other Things You Can Do With WSL And Expo

The fun doesn’t stop at just accessing Expo’s developer tools. Because you can forward any port to WSL, that means you can access the Chrome Debugger, use adb, integrate Flipper, monitor with Wireshark, the list goes on! You’ll also be running your Expo builds from within Linux, meaning any build tooling will work just as it would on a Linux or Mac workstation.

It’s a great time to build React Native apps, and now it’s easier than ever on Windows.