Get the best performance out of Development Containers on Windows …or… Troubleshoot Hot Module Reloading (HMR) not working on a NextJS or REACT Project running on a Development Container on Windows

The purpose of this document is to describe how to get the best performance out of a Development Container on Windows or how to troubleshoot the Hot Module Reloading (HMR) not working on a NextJS or REACT Project running on a Development Container on Windows.

Introduction

If you have been dabbling in creating development containers for some of your projects, and you use either create-react-app , vite or create-next-app and your development computer is a Windows computer, you might notice that the Hot Module Reloading feature either doesn’t work at all, or runs very slowly. The reason for this is because of the different file systems that Windows and Linux use. While you are developing on a Linux container, the differences between the host computer and the container can cause a bottleneck or unexpected behavior. The best way to resolve this is to use Windows Subsystem of Linux that is available on Windows 10 and above.

Install a Windows Subsystem Linux (WSL) Distribution

One of the easiest ways to install a WSL Distribution is to open the Microsoft Store, and search for “Ubuntu” and then click on the “Get” button for the version of your choice.

While you are at it. I also recommend downloading the “Windows Terminal” if you don’t already have it (it is not necessary, but a pretty handy tool to be able to have multiple consoles up for different distribution on different tabs).

Upgrade your Distribution to WSL2 (If applicable)

Check the version of WSL that your Distribution is using by executing the following command:

If your distribution is already at 2, then move on, otherwise execute the following command:
wsl.exe --set-version (distro name) 2
To set the default version to be 2 in the future execute the following command:
wsl.exe --set-default-version 2
To set that distribution as your default distribution execute the following command:
wsl --set-default (distro name)

Enable Integration in Docker Desktop

In your docker desktop go to Settings, and then Select Resources and WSL Integration. Ensure that the check box for Enable integration with my default WSL distro is checked.

Bring your project in to your WSL distro, and then run the development container there.

With all of this in place you now have a Linux Distribution running on your windows computer. In a way this WSL container has its own virtual hard drive. You can interact with it by going to \\wsl$\ in windows explorer and you can access the files on your distribution from there.

So, you can copy the files from your application there using drag and drop features of windows explorer.

Another way to get the project files in to your WSL Distribution is to use Linux commands in your Distribution. To access the Linux shell of your WSL either open a command prompt and type “wsl”, or if you have the Windows terminal installed, then it will appear as it’s own tab that you can open here.

Then you can execute the appropriate cp commands to copy files from /mnt/c, to somewhere within your distro like ~/myproject

If your project is on GitHub you can also use the git clone commands within the Linux shell as well.

While yes, you can use the project files within the /mnt/c drive, you will probably still experience some unexpected behavior. So, getting the files within the distribution is where you will get the most performance bang for your buck.

Install the necessary dependencies on to your Distribution (if applicable)

Usually, your dependencies will be in your development container. However, depending on your situation you may need to install dependencies on to your distribution, as your distribution is now the “host” machine.

A common dependency is nodejs. Below are the steps that you could take to install NodeJS in your WSL.

While you’re still in the Linux shell execute the following command:

curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
To make nvm available in your path execute the following command:
source ~/.bashrc  
Now that nvm is available you can install the node version that you need for your project. To install the latest long term support execute the following command:
nvm install --lts
Or you can install a specific version by doing something like this:
nvm install 18.16.0

Launch Visual Studio Code from within your WSL

With the way you have everything setup you should have “code” as an executable within your path. To confirm, execute the following command and confirm that you have a path to VS Code/bin in your path:

printenv
Change directories to wherever you copied your files including the .devcontainer folder. And then type code.
When you launch code you will notice that it says that you are connected to wsl
Assuming that your project has a .devcontainer folder and a devcontainer.json file, and the necessary files for your project you should now be able to Rebuild and Reopen in container by pulling up the command pallet with CTRL+SHIFT+P
At this point in time your project is now running in a dev container, but within the WSL, and thus both your docker container, and “host” computer (the WSL instance), are using the same file system, and the performance and features will be more closely to what you expect.

You will even see it in your docker desktop.

Now with that instance of Visual Studio Code open, do a CTRL+SHIFT+` to bring up a command prompt that is on that container.

You should be able to change directories to the project folder and run your dev command such as “npm run dev”, or whatever is appropriate for your project.

You should now notice that the HMR works like you expect.

Example: Create a new Vite + React App

Up to this point we have been discussing how to import an existing project. Let’s talk about starting a new project. After you have the WSL2 Distro installed and ready to go, you can begin to build more applications that use development containers. Here are the steps to create a new Vite + React App using WSL2.

Get in to your Linux shell (either by type wsl in a command prompt, or selecting the tab through the Terminal as mentioned earlier).

Change directories to the place that you would like to store your project files. For this example we are just going to use our home directory (~/), and then create a new directory that labels your project. In this example we will use “my-new-app”. Change directories in to “my-new-app” and execute “code .”

Once in Visual Studio code do a CTRL+SHIFT+P to bring up the command pallet and select the option for “Dev Containers: Add Dev Container Configuration Files”
Then select “Nodejs & TypeScript”
On the next screen, select the version that you would like to use. In this instance, I selected “18” as it is the current LTS as of this writing.

This will create a new .devcontainer/devcontianer.json file for you.

When prompted select the Reopen in Container option.

If you missed that prompt, you could do it by going to the command pallet (CTRL+SHIFT+P) and selecting the “Dev Containers: Rebuild and Reopen in Container” option.
Once the dev container is built you will be in a new instance of Visual Studio code editor.

Do a CTRL+SHIFT+` to bring up a terminal for the development container.

Execute the following command:

npm create vite@latest
I selected the following options.
As it directs, change directories to the vite-project directory, run the npm install, then the npm run dev command.

You should get a notice like this, go ahead and open in Browser.

You should see something like this:
Then edit the vite-project/src/App.tsx to something like this between lines 24 and 26
        <p>
          Hello World! Edit <code>src/App.tsx</code> and save to test HMR
        </p>
After that you should notice this in your terminal.
And this in your application:

Conclusion

Development Containers are great. If you are using Windows, then it is helpful to know that they run best under Windows Subsystem Linux (WSL2). Having the host computer, and the container using the same file system improves performance and the overall developer experience.

About Intertech

Intertech is a Software Development Consulting Firm that provides single and multiple turnkey software development teams, available on your schedule and configured to achieve success as defined by your requirements independently or in co-development with your team. Intertech teams combine proven full-stack, DevOps, Agile-experienced lead consultants with Delivery Management, User Experience, Software Development, and QA experts in Business Process Automation (BPA), Microservices, Client- and Server-Side Web Frameworks of multiple technologies, Custom Portal and Dashboard development, Cloud Integration and Migration (Azure and AWS), and so much more. Each Intertech employee leads with the soft skills necessary to explain complex concepts to stakeholders and team members alike and makes your business more efficient, your data more valuable, and your team better. In addition, Intertech is a trusted partner of more than 4000 satisfied customers and has a 99.70% “would recommend” rating.