Prerequisites:
- Windows 11/10
- WSL2
- NodeJS
- Admin Rights
- Up to Date Power Shell Version
- Dotenv
On one of the Top Secret project on Devhat community my team decided to work with Expo to create our MVP, Expo looks great but soon I figured out that it will make me suffer. ☠️
All my developer environment runs on WSL, Windows Subsistem Linux 2 to be precise, its been more than a year that I work with it, but soon I realize that its not that easy to run Expo with WSL, there's no straight to the point tutorial nor a updated tutorial on internet on how to make it, but I wasn't comfortable to install Node, Git and god knows what else I would need to install on my Windows just because of a single project, so I started a journey to find the golden way to run Expo with WSL.
And thank god, I managed to make it work!
I'll divide this tutorial in two, the first part is to make Expo works with WSL thought the QR code and, the second part, is how to make it work with Android Virtual Device (AVD), but keep in mind that this first step is required if you want to make it work with AVD.
WSL and Expo QR code
First, get this script, available as Gist as well, and move it to your root C:
on your Windows, the same place of your Program Files and Users folder, and name it forward_wsl2_ports.ps1
.
Its worth to mention that this script is a slightly change of this one, we needed to change it in order to make it work for people that has more than one IP on the wsl hostname -I
command. Also if your want to understand what this script actually solves I strongly recommend you to read the article
This script doesn't need any change if you use the default Expo port 8081
, but if your Expo run in another port you'll need to update the line 6
of the script adding the desired port, for instance $ports = @(8081,8089);
Opening WSL ports
Now on your Windows, open Power Shell as administrator and before run the command below make sure that your WSL is completely turned off, so close all WSL terminals and editors such as VSCode and then wsl --shutdown
.
With WSL turned off you can run the command below:
powershell.exe -ExecutionPolicy Bypass -f C:\forward_wsl2_ports.ps1
If everything went right you'll see something like that
This command opened the WSL ports for the IP returned on the first step of the command WSL IP 'the ip'
, in my case it opened just 8081
which is the default Expo port, but if you added more IP's there it will open that other ports too. Then you can press any key and close this Power Shell window.
Configuring the WSL Expo project
Go to your WSL2 and open your Expo project or, if your don't have any, create a new one with npx create-expo-app
and follow steps to create the project.
Open the project with your desired editor and lets add a new script on our package.json
file, this script will be a specific one to run the Expo project on through your WSL.
"scripts": {
/* other scripts */
"start:wsl": "REACT_NATIVE_PACKAGER_HOSTNAME=$(node get_network_local_ip.js) expo start"
}
We'll need to add the get_network_local_ip.js
file on the next step, but all that package.json
command does is run the JavaScript file to get your local internet IP address and then set it as the hostname for Expo instead use the default one!
The project will work if you replace the $(node get_network_local_ip.js)
with your local IP. To know your local IP you can go to, on Windows 11, Start -> Network & Internet -> Properties
and then look for IPv4 address
.
So, if you're a solo developer its "ok" if your script look like this
"start:wsl": "REACT_NATIVE_PACKAGER_HOSTNAME=19X.XXX.XX.XXX expo start"
But for teams this solution is not a good one, that's why we need the get_network_local_ip.js
script!
All that script does is search for the IP of your active internet network, but its worth to mention that this is a updated version of the command showed on Kendall article as well.
Kendall's current solution in package.json
to find the internet interface IPv4 is great, but it could lead to issues in scenarios where a different internet interface other than "Ethernet" is used or the IPv4 regex doesn't match 'IP Address'. Modifying package.json
for these local-specific configurations would result in unnecessary changes in every Merge Request. To avoid this, I've implemented a separate get_network_local_ip.js
script that leverages a .env.local
file for local configurations, ensuring a more flexible and MR-friendly approach.
I also updated the regex to look for the IP, but this is a idiom specific issue, if you want you can read the explanation below.
Why did I update the IP regex: I'm a Brazilian and so the original script
netsh.exe interface ip show address 'Ethernet' | grep 'IP Address' | sed -r 's/^.*IP Address:\\W*//'
don't work for me since mynetsh.exe
displays the interfaces inpt-br
noten-us
and that's a huge problem cause here "IP Address" becomes "Endereço IP", a word with aunicode
character that's very hard to work with bash scripts and even harder with a script that is somewhere between WSL and Power Shell. All my attempts to search for "Endereço IP" withgrep
were failures so, instead of replace the "IP Address:" section, on this updated script I look for the actual IP which was way easier. I also believe that this will work on many other idioms around the world, so its a more cross language solution.
Here's the updated command as a JavaScript file, its also available on this gist. Add it to the root of your project with the name get_network_local_ip.js
You'll also need the .env.local
file to define your local variables for your internet interface name and your regex to look for your IPv4 label.
Your interface name and IP regex
On your .env.local
you need to add the name of your internet interface and the regex to find your IPv4, here's how you can find it:
On Windows 11 go to Start -> Network & Internet -> Properties
, look for IPv4 address
and save the IP for later.
Then open your WSL terminal and run netsh.exe interface ip show address
, it will return a bunch of network interfaces, in my case its a lot of interfaces, but in your case you can have only few, either way we just want one of them, the one that the IP Address is the same as the IP we saved previously saved.
In my case Ethernet 3
is the interface that has the same IP, so I can update that LOCAL_CONNECTION_INTERFACE_NAME
environment variable with Ethernet 3
.
In your case it could be just Ethernet
, Ethernet 2
or even WiFi
, all depends of how and which internet port you're using to connect your device on the internet.
Now, on the left of your IP is how your "IP Address" is called on your idiom and with that you'll need to get the most of the word on your idiom, avoiding unicode
characters, to search for your IP later with the variable LOCAL_CONNECTION_IPV4_SEARCH
. In my case for instance if add the whole "Endereço IP" will throw a error cause 'ç' is a unicode
character, but if I search for Endere
it finds the right label!
You can test if your chosen word works running
netsh.exe interface ip show address 'YOUR_INTERFACE_NAME' | grep -a 'YOUR_IPV4_SEARCH'
In my case it is
netsh.exe interface ip show address 'Ethernet 3' | grep -a 'Endere'
If it returns something like "YOUR WORD: YOUR IP" it worked! In my case
Now we can add the value to the LOCAL_CONNECTION_IPV4_SEARCH
variable, my .env.local
is looking like this
LOCAL_CONNECTION_INTERFACE_NAME="Ethernet 3"
LOCAL_CONNECTION_IPV4_SEARCH="Endere"
Now test if your script is working, on the opened Expo project run node get_network_local_ip.js
and it should return your IPv4
If it returned your IP everything it setup! Now the only thing you need to do is check if your cellphone is connected to the same internet as your computer and then, on the Expo project, run
npm run start:wsl
You can notice if everything went well if Expo displays your IP as the Metro connection instead of another one
Now you can download the Expo App on your cellphone, scan the QR code and it should work as expected! 🥹
WSL and Expo AVD (Android Virtual Device)
For those who want to use Expo through a virtual device the tutorial continues here on how to run Expo on WSL with a Android Virtual Device!
If this tutorial helped you please leave a comment or a reaction!
Thank you for reading, see ya!
Top comments (3)
Man, I can't believe I will be first comment. I was on my own quest to solving this. You helped me with the final script to make it as smooth as possible.
I will add it to my blog with the due credits!! This post needs all the attention possible for developing in expo with Windows. I need to buy you a beer!
Cheers mate!
Man, you are the saviors of saviors. I appreciate your guidance through the bottom of my heart xoxo
Thank you so much. This is the best tutorial about how to setup wsl2 with react native.
You're the best!!!