Content posted here with the permission of the author Rahul Ojha, who is currently employed at Josh Software. Original post available here

Background
We had 4 React apps running on the local server. All apps were running on different ports because we can not start multiple React Apps on the same port. We had to build a single sign-on server. Out of 4 react apps one will be responsible for managing authentication and based on roles or department redirecting to other apps. The Auth app will get token from Auth API and will store it to local storage, and other apps will be using this token for authentication while calling APIs.
Problem Faced:
Now while calling API from any React app we need to send the token with it. Since the token is stored in local storage by Auth App which is using a different port so the local storage will not be accessible for other react apps.
You may think “Why didn’t you go with Cookies”, Yes cookies are shareable among HTTP ports but its size is very less which is 4 KB. So if you have to store permissions and anything else which is shareable and exceeding to 4 KB the cookies will not be useful.
Solution:
We will be using a single domain and will access different React apps using namespace in URL.
Example:
localhost:9292/app1 => app1 => localhost:3001 localhost:9292/app2 => app2 => localhost:3002 localhost:9292/app3 => app3 => localhost:3003 localhost:9292/app4 => app4 => localhost:3004
Here we need to use a reverse proxy server to do this. We will use Ruby Rack to create a proxy server. Why not use Nginx here? You can but there is a problem, React does not add namespace in the assets path so assets will not be loaded and you will see a blank white page always, and there is no way in development to add the namespace in asset path without ejecting CRA. If you have specified any value to homepage key in package.json file, then it will be automatically prefixed with assets path while creating a build in production mode.
So if you are Ruby developer then you are going to enjoy rest of the blog. But if you are not a Ruby developer there is no issue because Ruby is nice and easily understandable. You just need to follow the steps.
Step 1:
Install ruby You can use below link to install RVM and ruby. RVM is Ruby version manager.https://rvm.io/rvm/install
Step 2:
gem install rack
Step 3:
gem install rack-proxy
Step 4:
Create a file ./proxy_server.rb and add below code.
require 'rack-proxy' class ProxyServer < Rack::Proxy def rewrite_env(env) request = Rack::Request.new(env) if request.path.match('/app1') env["HTTP_HOST"] = "localhost:3001" @port = 3001 elsif request.path.match('/app2') env["HTTP_HOST"] = "localhost:3002" @port = 3002 elsif request.path.match('/app3') env["HTTP_HOST"] = "localhost:3003" @port = 3003 elsif request.path.match('/app4') env["HTTP_HOST"] = "localhost:3004" @port = 3004 # The below line is important to load assets. # So it detects app name from the first request to the app # which is stored in an instance variable and redirects # to that app for assets. elsif request.path.match('/static') || request.path.match('/assets') env['HTTP_HOST'] = "localhost:#{@port}" else env["HTTP_HOST"] = "localhost:3001" @port = 3001 end env end end
Step 5:
Add a file ./config.ru and add below code
require_relative './proxy_server' run ProxyServer.new
Step 6:
Run below command on the command line where you have stored above files. This command is responsible for starting your rack server.
rackup
Now your Rack server has started and ready do proxy pass. You just need to go at localhost:9292 and your default app which is app1 as per proxy_server file will be loaded to the browser. Port 9292 is default port defined for Rack server.
Conclusion:
By using Rack server you can run multiple react apps on the same domain in development environment with local storage and cookies shareable among all applications. This solution is not restricted to only React apps, it can be used for any other client-side frameworks too.
One thought on “Using Rack::Proxy To Serve Multiple React Apps On The Same Domain”