ESP32 Arduino: Serving a React.js app

In this tutorial we will check how to serve a React.js application from the ESP32, using the Arduino core and the HTTP async web server library. The tests of this tutorial were performed using a DFRobot’s ESP32 module integrated in a ESP32 development board.

Introduction

In this tutorial we will check how to serve a React.js application from the ESP32, using the Arduino core and the HTTP async web server library

React.js is a component based JavaScript library for frontend development, which is currently widely used and has a lot of support.

This post is focused on the code needed to serve the app from the ESP32 and not on writing the actual React code. Thus, we will be using an already existing React application sample, which can be seen here.

After entering the React app sample page, simply click “Download Source” button and a .zip file should get downloaded to your computer. Unzip it to a folder of your choice.

You should obtain a couple of different files, like shown in figure 1. For this tutorial, we will only need the demo.js and the index.html files, highlighted in red. Thus, you can delete all the other files and folders.

React rebound sample source files
Figure 1 – React.js sample app source files.

After deleting the unnecessary files and folders and leaving only the demo.js and the index.html, simply click on the index.html file so it opens in your web browser. You should see the same application from the samples website getting rendered locally in your machine.

So, these two files are the ones we will be serving from the ESP32. We will be serving them from the SPIFFS file system.

In order to upload these files to the SPIFFS file system, we will be using this Arduino IDE plugin. You can check a getting started tutorial on this previous post.

In short, you just need to open the Arduino IDE and create a new sketch, where Arduino the code from the section below will be written. After saving the sketch, you can click on the Sketch menu of the Arduino IDE and select the “Show Sketch folder” option.

Inside the sketch folder, simply create a folder called “data” and copy the index.html and demo.js files to that folder. The Arduino IDE SPIFFS upload plugin will upload all the content from this folder to the file system.

To do this upload, go back to the Arduino IDE and under the Tools menu simply click the “ESP32 Sketch Data Upload” option. The uploading procedure should begin.

Once the procedure finishes, both files should be available on the ESP32 SPIFFS file system, and then can be accessed and served from the Arduino application we will write below.

The tests of this tutorial were performed using a DFRobot’s ESP32 module integrated in a ESP32 development board.

The code

We will start by including the libraries that we will use in our code. We will include the WiFi.h, which will allow us to connect the ESP32 to a WiFi network, the ESPAsyncWebServer.h, which allows to setup a HTTP web server, and the SPIFFS.h, which we will use to interact with the SPIFFS file system.

Additionally, we will also need to declare the credentials for the WiFi network. In particular, we will need the network name and the network password.

Note that, as input, the constructor of this class receives the port where the server will be listening for incoming requests. We will use port 80, which is the default HTTP port.

To finalize the declaration of global variables, we will need an object of class AsyncWebServer. We will later use this class to configure the endpoints of our server and the corresponding handling functions.

#include "WiFi.h"
#include "SPIFFS.h"
#include "ESPAsyncWebServer.h"
 
const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

AsyncWebServer server(80); 

Moving on to the setup function, we will start by opening a serial connection, so we can output some messages from our program, to later be checked on the Arduino IDE serial monitor.

After that, we will mount the SPIFFS file system. We always need to initialize SPIFFS first, before we interact with it. Then we will take care of connecting the ESP32 to the WiFi network, using the previously declared credentials.

Serial.begin(115200);
 
if(!SPIFFS.begin()){
     Serial.println("An Error has occurred while mounting SPIFFS");
     return;
}
 
WiFi.begin(ssid, password);
 
while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
}
 
Serial.println(WiFi.localIP());

After the previously mentioned initialization procedures, we will take care of setting the server routes. First, we will need a route to serve the index HTML file we have uploaded before to the SPIFFS file system.

We will call this route “/“, since it will be the index route. It will only listen to HTTP GET requests and its handling function implementation will consist on serving the index.htmlfile.

In order to serve a file to the client that is contacting the server, we simply need to use one of the overloaded versions of the send method of the AsyncWebServerRequest object. Recall from previous tutorials that, when called, the route handling function will receive as input a pointer to an object of the mentioned class.

So, as first input of the send method we will pass the SPIFFS object, which will be used under the hood by the HTTP web server framework to access the file.

As second input we will pass a string with the path to the file we want to serve. The file is located on “/index.html“.

As third and last parameter of the send method, we will pass another string, with the content type of the file that will be served. This should be correctly specified so the client knows how to interpret the content.

In our case, since we are serving a HTML file, we should use the content type “text/html“.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
});

To finalize the routes setup, we still need to configure a second route to serve the JavaScript file that the HTML file will import.

The route for this endpoint will be called “/demo.js“, since this is the relative path that the index.html will use to obtain the JavaScript file.

Like before, this route will only listen to HTTP GET requests and use the send method to return back to the client the JavaScript file with the React.js application.

This file is located on the “/demo.js” path on the SPIFFS file system and the content type should be “text/javascript“, as shown below.

server.on("/demo.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/demo.js", "text/javascript");
});

After configuring the routes, the only thing left to do is calling the begin method on our server object, so it starts listening to incoming request.

server.begin();

The final source code can be seen below. Note that the main loop can be left empty since the web server framework we are using works asynchronously, meaning that we don’t need to periodically poll some object to handle incoming clients.

#include "WiFi.h"
#include "SPIFFS.h"
#include "ESPAsyncWebServer.h"
 
const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";
 
AsyncWebServer server(80);
 
void setup(){
  Serial.begin(115200);
 
  if(!SPIFFS.begin()){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
  }
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
 
  Serial.println(WiFi.localIP());
 
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });

  server.on("/demo.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/demo.js", "text/javascript");
  });
 
  server.begin();
}
 
void loop(){}

Testing the code

To test the code, first compile it and upload it to your ESP32 device, assuming that you have already uploaded the files to the SPIFFS file system beforehand. Once the procedure finishes, open the Arduino IDE and copy the IP address that gets printed.

Then, open a web browser of your choice and type the following in the address bar, changing #yourDeviceIp# by the IP you have just copied.

http://#yourDeviceIp#/

You should get an output similar to figure 2. As can be seen, the React.js app gets rendered and both the files are served from the ESP32.

Serving a React.js App using the ESP32 and the Arduino core
Figure 2 – Serving a React.js app from the ESP32.

Note that the third requests shown that fails corresponds to the browser trying to fetch a favicon for the website, which we are not serving. Please check this previous tutorial for an explanation on how to serve a favicon from the ESP32.

Related Posts

5 Replies to “ESP32 Arduino: Serving a React.js app”

  1. Hello,
    at “http://myESP32ipaddress/” I get no output in the browser (Firefox).

    Kind Regards

    Juergen B.

  2. Hello,
    at “http://myESP32ipaddress/” I get no output in the browser (Firefox).
    Kind Regards
    Juergen B.

Leave a Reply