When developing projects with React Native code, we were running into issues with dependencies and configurations that differed from machine to machine, causing build errors on some but not others. We decided to create a virtual machine that was correctly configured to build React Native code and then use Vagrant to quickly and easily run the virtual machine on different hosts to create a build environment that was more reliable. This would build the code without error regardless of the host machines' configuration.
To build an app for either Android or iOS, the virtual machine had to run Mac OS X (required iOS development tools are only available on Mac). Due to the license agreement, OS X must run on a Mac.
The first step was creating a virtual machine with an OS X image. Shared files require the installation of an image called "guest additions," however guest additions are unavailable for OS X, so the shared folder through VirtualBox had to be disabled, and an alternative for file sharing between the host, and the virtual machine had to be implemented.
If a network folder is set up on the host machine, the virtual machine can access it by using the IP address, username, and password of the user on the host machine. Even better, this can be done through a bash script, so once the virtual machine is running, the user can SSH in and run the script, quickly mounting the network folder and allowing shared files between the systems. This is important because the React code will is not on the virtual machine, but on the host for speed and ease of access. So building a project is as simple as setting up the project folder for network access and mounting the project folder from the virtual machine.
The next step was installing and configuring all of the necessary software to build React Native code while keeping the size of the disk image as small as possible. Much of the React Native dependencies could be installed using Homebrew. The most critically required installs were Xcode and the Android SDK.
To be useful, the Virtual Machine has to be able to output the code it builds to a screen, so developers can see the changes they are making. Xcode comes with a simulator for iOS devices, which creates a virtual device that can display the output. Unfortunately, as one might expect when running a simulator inside of a virtual machine, it ran very slowly and was not efficient as a development environment. Besides the fact that the iOS emulator ran slowly, we soon discovered that simulating Android devices from within a virtual machine is entirely unsupported. To circumvent this, we were able to get the build to output to a physical device, both iOS and Android, connected to the host via USB.
This stable development environment has contributed significantly to the speed of mobile app development, relieving the frustration and time spent figuring out the problem when a build fails. It is also easier to maintain than many host machines since only the virtual machine has to be updated, tested, and then accessed by all developers.