DEV Community

Cover image for Expo QR code on Windows Subsystem for Linux (WSL2)
Alecell
Alecell

Posted on

Expo QR code on Windows Subsystem for Linux (WSL2)

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
Enter fullscreen mode Exit fullscreen mode

If everything went right you'll see something like that

power shell output after run the script

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"
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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 my netsh.exe displays the interfaces in pt-br not en-us and that's a huge problem cause here "IP Address" becomes "Endereço IP", a word with a unicode 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" with grep 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.

output of the conection interfaces on windows

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'
Enter fullscreen mode Exit fullscreen mode

In my case it is

netsh.exe interface ip show address 'Ethernet 3' | grep -a 'Endere'
Enter fullscreen mode Exit fullscreen mode

If it returns something like "YOUR WORD: YOUR IP" it worked! In my case

output of the filter on the netsh.exe command

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"
Enter fullscreen mode Exit fullscreen mode

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

IP as return of the javascript script

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
Enter fullscreen mode Exit fullscreen mode

You can notice if everything went well if Expo displays your IP as the Metro connection instead of another one

expo output your local ip as Metro connection

Now you can download the Expo App on your cellphone, scan the QR code and it should work as expected! 🥹

expo working on my own device

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 (0)