Not sure if this is a Kubernetes, ingress-nginx
, or ReactJS (create-react-app
) issue...
Project Structure
new-app/
client/
src/
App.js
index.js
Test.js
package.json
k8s/
client.yaml
ingress.yaml
server/
skaffold.yaml
Issue
192.168.64.5/client
when the cluster is spun up with Skaffold192.168.64.5/client
and blank screenBasically, it is trying to serve static files from /static
, but I need them to come from /client/static
Propsed Solutions
Assuming this is a ReactJS issue, the solutions have been the following:
homepage
in the package.json
basename
in the react-router-dom
None seem to work in my case. Still shows assets trying to be served from /static
instead of /client/static
.
ReactJS App Code
// App.js
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import './App.css';
import Test from './Test';
const App = () => {
return (
<BrowserRouter
basename='/client'>
<>
<Route exact path='/' component={Test} />
</>
</BrowserRouter>
);
}
export default App;
// Test.js
import React, { useState, useEffect } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';
const Test = () => {
const [data, setData] = useState('');
useEffect(() => {
const fetchData = async () => {
const result = await axios('/api/auth/test/');
setData(result.data);
};
fetchData();
}, []);
return (
<div className='App'>
<header className='App-header'>
<img src={logo} className='App-logo' alt='logo' />
<p>
Edit <code>src/App.js</code> and save to reload!
</p>
<p>
{data}
</p>
<a
className='App-link'
href='https://reactjs.org'
target='_blank'
rel='noopener noreferrer'
>
Learn React
</a>
</header>
</div>
)
};
export default Test;
{
"name": "client",
"version": "0.1.0",
"private": true,
"homepage": "/client",
"dependencies": {
"axios": "^0.19.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Kubernetes/Skaffold and Docker Manifests
# Dockerfile.dev
FROM node:alpine
EXPOSE 3000
WORKDIR '/app'
COPY ./client/package.json ./
RUN npm install
COPY ./client .
CMD ["npm", "run", "start"]
# ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/add-base-url: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /client/?(.*)
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
# client.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: client-deployment
spec:
replicas: 3
selector:
matchLabels:
component: client
template:
metadata:
labels:
component: client
spec:
containers:
- name: client
image: clientappcontainers.azurecr.io/client
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: client-cluster-ip-service
spec:
type: ClusterIP
selector:
component: client
ports:
- port: 3000
targetPort: 3000
# skaffold.yaml
apiVersion: skaffold/v1beta15
kind: Config
build:
local:
push: false
artifacts:
- image: clientappcontainers.azurecr.io/client
docker:
dockerfile: ./client/Dockerfile.dev
sync:
manual:
- src: "***/*.js"
dest: .
- src: "***/*.html"
dest: .
- src: "***/*.css"
dest: .
deploy:
kubectl:
manifests:
- manifests/ingress.yaml
- manifests/client.yaml
So what am I doing wrong here?
EDIT:
I should note that things work fine when doing this though:
- path: /?(.*)
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
Repo to demo the issue:
Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in package.json (homepage). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the URL you provide (hostname included). This may be particularly useful when using a CDN to host your application.
There are three ways to fix this problem:
{
...
homepage: "/client"
...
}
Reference:
https://create-react-app.dev/docs/advanced-configuration/
Apparently, this is not possible currently in CRA in a dev environment:
https://github.com/facebook/create-react-app/issues/8222#issuecomment-568308139