fix(ssr): inject fresh station config into CSR shell to eliminate flash
CI Pipeline / backend-test (push) Successful in 18m48s
CI Pipeline / frontend-test (push) Successful in 24s
CI Pipeline / frontend-build (push) Successful in 32s
CI Pipeline / backend-lint (push) Successful in 10s
CI Pipeline / backend-test (pull_request) Successful in 20m7s
CI Pipeline / frontend-test (pull_request) Successful in 24s
CI Pipeline / frontend-build (pull_request) Successful in 32s
CI Pipeline / backend-lint (pull_request) Successful in 10s
CI Pipeline / quality-gate (push) Successful in 3s
CI Pipeline / quality-gate (pull_request) Successful in 4s

The CSR shell previously rendered with hardcoded DEFAULT_CONFIG values,
then the client-side API call replaced them 50-500ms later, causing a
visible 'flash of stale content' (wrong colors, wrong station name).

Fix: SSR server fetches live station config from the backend API before
serving the CSR shell, injecting it as:
- Inline <script> seeding window.__STATION_CONFIG (client reads sync)
- Inline <style> setting CSS custom properties (correct colors first paint)

Also adds no-cache Cache-Control headers on HTML page responses to
prevent browsers from caching stale content.

StationConfigService now reads window.__STATION_CONFIG on construction
instead of always starting with DEFAULT_CONFIG.
This commit is contained in:
robot committed 2026-08-09 00:53:50 +00:00
1 parent 9561339cf5
commit e44f27d1cd
4 files changed
+221 -22

No files matched your search

+12 -1
View File
@@ -74,7 +74,18 @@ export class StationConfigService {
private themeService = inject(ThemeService);
private baseUrl = `${getAppConfig().apiBaseUrl}/api/station-config`;
readonly config = signal<StationConfig>(DEFAULT_CONFIG);
/**
* Read pre-seeded config injected by the server at runtime.
* The SSR server fetches fresh station config and injects it as
* `window.__STATION_CONFIG` before the Angular bundle loads.
* This eliminates the DEFAULT_CONFIG flash: the client bootstraps
* with real data instead of hardcoded defaults.
*/
readonly config = signal<StationConfig>(
typeof window !== 'undefined' && (window as any).__STATION_CONFIG
? (window as any).__STATION_CONFIG as StationConfig
: DEFAULT_CONFIG,
);
/** Load station config from the API. Falls back to defaults on error. */
async load(): Promise<void> {