I’m facing an issue with my React frontend (built with rsbuild) and my Node.js REST API.
Setup
- Frontend: React (rsbuild)
- Backend: Node.js REST API (pm2)
- Server: Windows Server
- Proxy: Nginx (serves frontend and proxies API requests)
Local development
- Running
npm run dev→ everything works fine. - API calls resolve correctly.
Production test on my PC
- Ran
npm run buildfor frontend, served with nginx proxy (/api), backend running with pm2 → also worked fine. - Other PCs on the same network could access it.
Production on the actual server
- Cloned both frontend and backend from git (instead of copying from dev).
- Ran npm run build for frontend, pm2 for backend.
- Backend is running fine at http://ip:8081/api/....
- Frontend is being served fine.
Problem: The frontend is not fetching my backend. Instead of hitting /api/..., the request URL looks like:
http://ip:8081/sales/undefined/api/reportqueries
http://ip:8081/undefined/api/query1
Notice the extra /sales and undefined.
I can only think that my .env.production is not working.
Here are some parts of the code (comment if you need more code for help)
rsbuild.config.ts
import { defineConfig } from "@rsbuild/core";
import { pluginReact } from "@rsbuild/plugin-react";
export default defineConfig({
plugins: [pluginReact()],
html: {
title: "name",
favicon: "public/favicon0.ico",
},
source: {
define: {
RSBUILD_API_BASE: JSON.stringify(process.env.RSBUILD_API_BASE),
},
},
});
.env.production
RSBUILD_API_BASE=/api
also tested
RSBUILD_API_BASE=
usage in code
const res = await fetch(`${RSBUILD_API_BASE}/api/reportqueries`);
Some are like
const res = await fetch(`${RSBUILD_API_BASE}/api/query/${queryCode}`, {
signal: controller.signal
});
// queryCode is the endpoint like query1, query2 query3
// src/hooks/useApi.ts
import { useEffect, useState } from 'react';
import axios from 'axios';
export function useApiQuery<T = any>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<any>(null);
useEffect(() => {
axios.get(RSBUILD_API_BASE + url)
.then((res) => setData(res.data))
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
const { data: dataCard1, loading: loading1 } =
useApiQuery<QC001Response[]>("/api/query/QC001");
const dataCard3 = useApiQuery<QC003Response[]>("/api/query/QC006");
nginx.conf (simplified)
server {
listen 8081;
server_name localhost;
root C:/path/to/frontend/dist;
location / {
index index.html;
try_files $uri /index.html;
}
location /api {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
}
}