Deploy React and Vite with nginx, SPA routes and caching
Build a React app, configure nginx for nested routes and asset caching, and deploy the site on Inquir Compute.
After npm run build, a Vite React application is a set of HTML, JavaScript and CSS files. Serving them does not require a Vite development server. This guide packages nginx for Inquir Compute and handles direct navigation to nested SPA routes.
Separate building from serving
Check that npm ci and npm run build succeed locally and produce dist. If you configured another build.outDir, change the Dockerfile copy path. vite preview is a local build-preview tool, not a production server; see the Vite deployment guide.
FROM node:22-bookworm-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginxinc/nginx-unprivileged:stable-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/ /usr/share/nginx/html/
EXPOSE 8080
Pin tested image versions or digests for reproducible production releases. Exclude .env, node_modules, .git and local dist through .dockerignore so builds do not depend on laptop artifacts.
Configure routing and caching
Create nginx.conf:
server {
listen 8080;
server_name _;
root /usr/share/nginx/html;
index index.html;
absolute_redirect off;
location = /healthz {
default_type text/plain;
return 200 "ok\n";
}
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
location / {
add_header Cache-Control "no-cache";
try_files $uri $uri/ /index.html;
}
}
The index.html fallback lets React Router handle a direct visit to /settings/profile. Missing JavaScript under /assets/ must instead return 404. Returning HTML as JavaScript causes MIME errors or Unexpected token '<'.
Year-long caching suits files with content hashes in their names. HTML should revalidate so browsers discover a new build. Do not make the entire site immutable.
Deploy on Inquir
After configuring the CLI, run from the project directory:
inquir apps create react-site --ingress public --port 8080 --health-path /healthz
inquir apps deploy react-site --promote
inquir apps status react-site
Use the URL returned by status. Test the homepage, direct navigation to an existing nested route and reloading that route. nginx does not create React pages absent from your router. Also request /assets/missing.js; it should return 404.
Vite variables are not secrets
Values of VITE_* used by client code become part of the browser bundle. They may contain a public API URL, but never a database password or model-provider key. Changing a running nginx environment variable does not rewrite compiled JavaScript. Rebuild the application or explicitly implement runtime loading of public configuration.
For an API on another domain, allow the appropriate origin in the API’s CORS settings. Frontend configuration cannot fix server-side authorization. Use the application docs for custom domains and the complete static-react-vite example as a starting point.