Skip to content

Instantly share code, notes, and snippets.

@bergmannjg
Last active December 1, 2024 08:09
Show Gist options
  • Save bergmannjg/461958db03c6ae41a66d264ae6504ade to your computer and use it in GitHub Desktop.
Save bergmannjg/461958db03c6ae41a66d264ae6504ade to your computer and use it in GitHub Desktop.
Building a react native app in WSL2

Building a react native app in WSL2

Install, build and debug a react native app in WSL2 (Windows Subsystem for Linux) and Ubuntu.

Install tools in Windows

  • Install WSL2 and Ubuntu, see here
  • Install Android Studion, see here
  • Install Viusal Studio Code, see here

Install tools in WSL2

  • Install java-8-openjdk in WSL2 (sudo apt-get install openjdk-8-jre)
  • Install Android SDK cmdline tools in WSL2, see here and adjust directory structure, see here
  • Install nodejs in WSL2, see here

Set environment variables in .profile or .bash_profile

export ANDROID_HOME=/home/xxx/Android/cmdline-tools/latest
export ANDROID_SDK_ROOT=/home/xxx/Android

PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
PATH=$PATH:$ANDROID_HOME/bin

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

Connect to android hardware device from WSL2

To debug on a hardware device connect to android device via usbip from WSL2 (thanks to @cjshearer):

Connect to android virtual device in Windows

To debug on a virtual device create a virtual device (e.g. Nexus_5X_API_29) in windows with Android Virtual Device Manager from Android Studio.

Start android virtual device in Windows

Start Android virtual device (e.g. Nexus_5X_API_29) in windows

"C:\Program Files (x86)\Android\android-sdk\emulator\emulator.exe" -avd Nexus_5X_API_29

Start adb server in Windows

adb kill-server
adb -a nodaemon server start

Change firewall rule for adb.exe on first usage in Defender Popup or with Windows Defender Firewall allowing access for the public profile, because the vEthernet (Wsl) adapter belongs to the public profile

Enable access to adb server from WSL2

Set environment variable to access adb server, WSL_HOST is ip of vEthernet (WSL) interface in windows

export WSL_HOST=$(tail -1 /etc/resolv.conf | cut -d' ' -f2)
export ADB_SERVER_SOCKET=tcp:$WSL_HOST:5037

Somtimes adb crashes using the environment variable config. One solution is to use socat (thanks to @tuanna1601).

Unset the environment variable if necessary.

unset ADB_SERVER_SOCKET

Install socat (eg. sudo apt-get install socat). Socat relays the requests from wsl2 to windows using the following command:

socat -d -d TCP-LISTEN:5037,reuseaddr,fork TCP:$(cat /etc/resolv.conf | tail -n1 | cut -d " " -f 2):5037

Enable access to metro bundler from Windows

The metro bundler is running in WSL2, listening on port 8081. Windows 10 version 2004 brings network forwarding from WSL2 to Windows. So the app can connect to the metro bundler from the emulator via Windows localhost.

Sometimes there are problems with the network forwarding. A work around is to use the following script.

WSL_CLIENT is ip of WSL2.

iex "netsh interface portproxy delete v4tov4 listenport=8081 listenaddress=127.0.0.1" | out-null;
$WSL_CLIENT = bash.exe -c "ifconfig eth0 | grep 'inet '";
$WSL_CLIENT -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
$WSL_CLIENT = $matches[0];
iex "netsh interface portproxy add v4tov4 listenport=8081 listenaddress=127.0.0.1 connectport=8081 connectaddress=$WSL_CLIENT"

Connect to Windows Subsystem for Android

To debug the app running on Windows Subsystem for Android (WSA).

Install Windows Subsystem for Android.

Start adb server in Windows.

Enable access to adb server from WSL2.

Enable access to metro bundler from Windows Subsystem for Android

The metro bundler is running in WSL2, listening on port 8081.

To enable access from WSA to WSL2, configure adb reverse port forwarding on WSA.

Connect to the WSA via 127.0.0.1:58526 and execute adb reverse.

adb connect 127.0.0.1:58526
adb reverse tcp:8081 tcp:8081 

Create react native app in WSL2

npx react-native init AwesomeProject

Build app in WSL2

Add paraameter in file proguard-rules.pro to ignore okhttp3 warnings

-dontwarn okhttp3.internal.platform.*

Start metro JavaScript bundler and bind to an ipv4 address to enable port forwarding to windows

npx react-native start --host 127.0.0.1

Build app, set device as parameter deviceId from result of adb devices

  • deviceId emulator: emulator-5554
  • deviceId WSA: 127.0.0.1:58526
npx react-native run-android --variant=debug --deviceId <deviceId>

Debug app in Visual Studio Code from WSL2

Start vs code in WSL2

code .

and install extensions for VS Code

  • Remote - WSL
  • React Native Tools

VS Code UI runs in windows and the VS Code Server runs in WSL2, see here

Add a launch configuration in file launch.json with specified type and request

"name": "Attach to packager",
"cwd": "${workspaceFolder}",
"type": "reactnative",
"request": "attach"

Build app, attach to packager and start debugging, see here.

@josersleal
Copy link

wsa is dead

@RenaudAubert
Copy link

@vagnerlandio Thank you so much !
This guide used to work for me but after upgrading to react-native 0.73 it stopped working.

⚠️ If you're planning on using react-native > 0.71 and can connect both your PC and smartphone to the same network I highly recommend doing what's described in this comment.

@Se7enSe7enSe7en
Copy link

Good news, using the new mirrored mode networking feature of WSL2, the setup part for connecting the device or emulator to the project server is now simpler.

  1. enable mirrored mode networking through the .wslconfig file (usually located in C:\Users\<user_name>)
[wsl2]
networkingMode=mirrored
  1. add this in the rc file (eg. .bashrc), so that when we run the project in wsl it uses the adb in windows
### Make alias for adb in Windows so that it can be called within WSL
alias adb="/mnt/c/Users/<user_name>/AppData/Local/Android/Sdk/platform-tools/adb.exe"

thats pretty much it.

Also make sure the firewall isn't the way by adding inbound rules with the ports for adb (5037) and the project server (usually 8081)

Before I had to add export WSL_HOST_IP="$(tail -1 /etc/resolv.conf | cut -d' ' -f2)", export ADB_SERVER_SOCKET=tcp:$WSL_HOST_IP:5037 and export REACT_NATIVE_PACKAGER_HOSTNAME=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') in the rc file. And to connect my physical device and the project server I had to run adb kill-server and adb -a nodaemon server start in windows first, every time I want to start the project.

Now with this we can just start the project directly and it should now connect to the physical device.

Big thanks for the people who contributed to this guide, hope this helps someone.

@Se7enSe7enSe7en
Copy link

Good news, using the new mirrored mode networking feature of WSL2, the setup part for connecting the device or emulator to the project server is now simpler.

  1. enable mirrored mode networking through the .wslconfig file (usually located in C:\Users\<user_name>)
[wsl2]
networkingMode=mirrored
  1. add this in the rc file (eg. .bashrc), so that when we run the project in wsl it uses the adb in windows
### Make alias for adb in Windows so that it can be called within WSL
alias adb="/mnt/c/Users/<user_name>/AppData/Local/Android/Sdk/platform-tools/adb.exe"

thats pretty much it.

Also make sure the firewall isn't the way by adding inbound rules with the ports for adb (5037) and the project server (usually 8081)

Before I had to add export WSL_HOST_IP="$(tail -1 /etc/resolv.conf | cut -d' ' -f2)", export ADB_SERVER_SOCKET=tcp:$WSL_HOST_IP:5037 and export REACT_NATIVE_PACKAGER_HOSTNAME=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') in the rc file. And to connect my physical device and the project server I had to run adb kill-server and adb -a nodaemon server start in windows first, every time I want to start the project.

Now with this we can just start the project directly and it should now connect to the physical device.

Big thanks for the people who contributed to this guide, hope this helps someone.

Ok so after a few days I've realized that this only works if I type adb devices in wsl terminal before starting the expo project, this is because I had 2 copies of adb, one in wsl and the other in windows, and this starts the adb server in windows.

After digging through the source code of expo, found out that expo checks if adb server is already running, if it is, it uses that server, this explains why running the adb server in windows then starting the expo project in wsl works. We can also see that in assertSdkRoot() (source) it tries to find the adb through the environment variable $ANDROID_HOME, so this explains why when we start the project it still runs the adb in wsl.

In order for us to no longer do the extra step of starting the adb server in windows through typing adb devices or adb start-server in wsl terminal before we start the project, a hacky way to fix this is to make a symlink (not really the same but think of it as a shortcut file windows but in linux) in the platform-tools folder in wsl that points to the adb in windows.

Type this is wsl terminal:

ln -s /mnt/c/Users/<user_name_windows>/AppData/Local/Android/Sdk/platform-tools/adb.exe /home/<user_name_wsl>/Android/platform-tools/adb

with this, we've eliminated the extra step, now we can just start the project in wsl and it should connect to your physical device 😄

@Kulunkulu
Copy link

Kulunkulu commented Aug 15, 2024

Good news, using the new mirrored mode networking feature of WSL2, the setup part for connecting the device or emulator to the project server is now simpler.

  1. enable mirrored mode networking through the .wslconfig file (usually located in C:\Users\<user_name>)
[wsl2]
networkingMode=mirrored
  1. add this in the rc file (eg. .bashrc), so that when we run the project in wsl it uses the adb in windows
### Make alias for adb in Windows so that it can be called within WSL
alias adb="/mnt/c/Users/<user_name>/AppData/Local/Android/Sdk/platform-tools/adb.exe"

thats pretty much it.
Also make sure the firewall isn't the way by adding inbound rules with the ports for adb (5037) and the project server (usually 8081)
Before I had to add export WSL_HOST_IP="$(tail -1 /etc/resolv.conf | cut -d' ' -f2)", export ADB_SERVER_SOCKET=tcp:$WSL_HOST_IP:5037 and export REACT_NATIVE_PACKAGER_HOSTNAME=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') in the rc file. And to connect my physical device and the project server I had to run adb kill-server and adb -a nodaemon server start in windows first, every time I want to start the project.
Now with this we can just start the project directly and it should now connect to the physical device.
Big thanks for the people who contributed to this guide, hope this helps someone.

Ok so after a few days I've realized that this only works if I type adb devices in wsl terminal before starting the expo project, this is because I had 2 copies of adb, one in wsl and the other in windows, and this starts the adb server in windows.

After digging through the source code of expo, found out that expo checks if adb server is already running, if it is, it uses that server, this explains why running the adb server in windows then starting the expo project in wsl works. We can also see that in assertSdkRoot() (source) it tries to find the adb through the environment variable $ANDROID_HOME, so this explains why when we start the project it still runs the adb in wsl.

In order for us to no longer do the extra step of starting the adb server in windows through typing adb devices or adb start-server in wsl terminal before we start the project, a hacky way to fix this is to make a symlink (not really the same but think of it as a shortcut file windows but in linux) in the platform-tools folder in wsl that points to the adb in windows.

Type this is wsl terminal:

ln -s /mnt/c/Users/<user_name_windows>/AppData/Local/Android/Sdk/platform-tools/adb.exe /home/<user_name_wsl>/Android/platform-tools/adb

with this, we've eliminated the extra step, now we can just start the project in wsl and it should connect to your physical device 😄

@Se7enSe7enSe7en
I installed Windows 10 because I dont want BSOD for Win 11
I am trying to run a -Bare React Native Project- and not React-Expo

Have you tested your mirrored mode networking to see if it works for Bare React Native?

My head is really spinning at this point from reading so many threads
when i apply the configs of a particular thread, it results in another error
and now i am entrapped in a vicious loop

Can you create your own New Gist and simply link to it here?
I ask this because i am unsure of how to setup my dev environment following the configs in this current gist alongside this mirrored mode networking feature

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment