feat: make API base URL runtime-configurable
The PROD image baked PUBLIC_API_BASE_URL at build time (rsbuild inlines
PUBLIC_* vars), so a prebuilt image could only ever target a same-origin
'/api/v1' and needed a reverse proxy in front. Move the operator default to
runtime so one image can point at any backend origin without rebuilding.
- public/config.js: committed stub setting window.__APP_CONFIG__ = {}, used
as the dev/build-time default and overwritten in prod at container start.
- rsbuild.config.ts: inject a classic (non-deferred) <script src="/config.js">
into <head> so it runs before the deferred app bundle.
- src/config/env.ts: DEFAULT_API_BASE_URL now resolves
window.__APP_CONFIG__.apiBaseUrl > import.meta.env.PUBLIC_API_BASE_URL >
'/api/v1'. The user-chosen instance still wins over all of these.
- dockerfiles/30-runtime-config.sh: nginx /docker-entrypoint.d hook that
regenerates /config.js from $PUBLIC_API_BASE_URL on every start.
- Dockerfile.prod: install the hook (build-time ARG is now just a fallback).
- nginx.conf: serve /config.js with Cache-Control: no-store.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+21
-1
@@ -1,2 +1,22 @@
|
||||
/**
|
||||
* Default backend base URL — the operator-set fallback used when no specific
|
||||
* instance is active. Resolution order:
|
||||
*
|
||||
* 1. window.__APP_CONFIG__.apiBaseUrl — runtime, injected by the container
|
||||
* at start from $PUBLIC_API_BASE_URL (see public/config.js). Lets one
|
||||
* prebuilt image point at any backend origin without rebuilding.
|
||||
* 2. import.meta.env.PUBLIC_API_BASE_URL — build-time default (rsbuild inlines
|
||||
* PUBLIC_* vars). Used in local dev and as a baked fallback.
|
||||
* 3. '/api/v1' — same-origin relative path (works behind a reverse proxy).
|
||||
*
|
||||
* The user's chosen instance still wins over all of these — see
|
||||
* runtime-config.ts / instances.ts.
|
||||
*/
|
||||
function runtimeApiBaseUrl(): string | undefined {
|
||||
if (typeof window === 'undefined') return undefined;
|
||||
const value = window.__APP_CONFIG__?.apiBaseUrl;
|
||||
return value ? value : undefined;
|
||||
}
|
||||
|
||||
export const DEFAULT_API_BASE_URL =
|
||||
import.meta.env.PUBLIC_API_BASE_URL ?? '/api/v1';
|
||||
runtimeApiBaseUrl() ?? import.meta.env.PUBLIC_API_BASE_URL ?? '/api/v1';
|
||||
|
||||
Vendored
+8
@@ -5,3 +5,11 @@ interface ImportMetaEnv {
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
||||
// Runtime operator config injected by /config.js before the app bundle loads
|
||||
// (written from $PUBLIC_API_BASE_URL at container start). See src/config/env.ts.
|
||||
interface Window {
|
||||
__APP_CONFIG__?: {
|
||||
apiBaseUrl?: string;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user