I'm trying to find a way how to host multiple (currently 2) React applications, each created with CRA. Both apps should run behind a single instance of NGINX and be accessible in a separate directory:
app1 -> http://localhost/app1
app2 -> http://localhost/app2
The 2 React applications where created like this:
npx create-react-app app1
npx create-react-app app2
To host both React applications using NGINX, the production build of each CRA app (npm run build
) is copied to NGINX static directory /var/www/app[1|2]
# App1
npm run build
cp build/* /var/www/app1
# App2
npm run build
cp build/* /var/www/app2
This is how NGINX can be setup to host a single CRA app:
# /etc/nginx/conf.d/default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /var/www/app1;
index index.html;
}
}
Now I'm trying to extend this example so both CRA apps are hosted by one NGINX.
Which modifications are necessary, both to NGINX site.conf
and each React application itself?
I pushed a code showing my (incomplete) example above to Github for reference: https://github.com/wolkenarchitekt/multiple-cra-apps-behind-nginx. The code is using docker-compose for simplicity, but in the end the whole stack should run without Docker, so running separate Docker services for each React app is not an option.
In order to run both React apps on the same domain but different subfolders, you should just need two location
blocks:
root /var/www;
location /app1/ {
index index.html;
}
location /app2/ {
index index.html;
}
The necessary changes in the React apps usually include:
homepage
field in the package.json
as described herebasename
for BrowserRouter
to your subdirectory: <BrowserRouter basename='/app1'>
EDIT:
After checking out your repo (before you pushed the new branch) I just got it working with the following Dockerfile (way worse for development since every code change requires a rebuild, I just like multistage builds and this would be more suited for a production environment):
FROM node:16 as builder1
WORKDIR /var/app
COPY app1/package.json .
COPY app1/package-lock.json .
RUN npm i
COPY app1/public/ ./public
COPY app1/src/ ./src
RUN npm run build
FROM node:16 as builder2
WORKDIR /var/app
COPY app2/package.json .
COPY app2/package-lock.json .
RUN npm i
COPY app2/public/ ./public
COPY app2/src/ ./src
RUN npm run build
FROM nginx:mainline-alpine
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./nginx/site.conf /etc/nginx/conf.d/default.conf
COPY --from=builder1 /var/app/build/ /var/www/app1
COPY --from=builder2 /var/app/build/ /var/www/app2
The following site.conf
worked for me:
server {
listen 80;
listen [::]:80;
server_name localhost;
root /var/www;
location /app1 {
index index.html;
}
location /app2 {
index index.html;
}
}
I just had to change homepage
to /app1
and /app2
respectively, change app2/App.js
to actually output App2
, and then
docker build . -t testreactmultiple:latest
docker run -it -p 3000:80 docker.io/library/testreactmultiple:latest
I hope this helps you reproduce the working container that errors when the index is requested but works fine when /app1
or /app2
is requested.