Configuring React SPAs at Runtime

Configuring a SPA is a tricky affair. I found some tools to make it a little bit easier, but it should still be used with a fair amount of caution.

The App

I built a small React UI to view some additional information that I am storing in my Unifi Controller for network devices. Using the notes field on the Unifi device, I store some additional fields in JSON format in order for other applications to use. It is nothing wild, but allows me to have some additional detail on my network devices.

In true API-first fashion, any user-friendly interface is an afterthought… Since most of my interaction with the service is through Powershell scripts, I did not bother to create the UI.

However, I got a little tired of firing up Postman to edit a few things, so I spun up a React SPA for the task.

Hosting the SPA

I opted to host the SPA in its own container running Nginx to host the files. Sure, I could have used thrown the SPA inside of the API and hosted it using static files, which is a perfectly reasonable and efficient method. My long-term plan is to create a new “backend for frontend” API project that hosts this SPA and provides appropriate proxying to various backend services, including my Unifi API. But I want to get this out, so a quick Nginx container it is.

I previously posted about creating a simple web server image using Nginx. Those instructions (and an important update for React) served me well to get my SPA running, but how can I configure the application at runtime? I want to build the image once and deploy it any number of times, so having to rebuild just to change a URL seems crazy.

Enter react-runtime-config

Through some searching, I found the react-runtime-config library. This library lets me set configuration values either in local storage, in a configuration file, or in the application as a default value. The library’s documentation is solid and enough to get get you started.

But, wait, how do I use this to inject my settings??? ConfigMaps! Justin Polidori describes how to use Kubernetes ConfigMaps and volume mounts to replace the config.js file in the container with one from the Kubernetes ConfigMap.

It took a little finagling since I am using a library chart for my Helm templating, but the steps were something like this:

  1. Configure the React app using react-runtime-config. I added a config.js file to the public folder, and made sure my app was picking settings from that file.
  2. Create a ConfigMap with my window.* settings.
  3. Mount that ConfigMap in my container as /path/to/public/config.js

Viola! I can now control some of the settings of my React App dynamically.

Caveat Emptor!

I cannot stress this enough: THIS METHOD SHOULD NOT BE USED FOR SECRET OR SENSITIVE INFORMATION. Full stop.

Generally, the problem with SPAs, whether they are React, Angular, or pick your favorite framework, is that they live on the client in plain text. Hit F12 in your favorite browser, and you see the application code.

Hosting settings like this means the settings for my application are available just by navigating to /config.js. Therefore, it is vital that these settings are not in any way sensitive values. In my case, I am only storing a few public URLs and a Client ID, none of which are sensitive values.

The Backend for Frontend pattern allows for more security and control in general. I plan on moving to this when I create a BFF API project for my template.


Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *