Files
adastra_app/docs/decisions/0013-json-assets-httpclient-migration.md
T
julien fa00719a3e feat(herowars): migrate JSON static imports to HttpClient assets
Replace all TypeScript JSON imports with an HWDataService that loads
6 data files from /assets/files-data/ via HttpClient with shareReplay(1).
Update all 9 consumer components to subscribe asynchronously. Remove
unused qcm-bpa.json import and dead methods from QcmComponent.
Add ADR 0013 documenting the decision.
2026-04-26 23:46:35 +02:00

3.8 KiB
Raw Blame History

Migrate HeroWars static JSON imports to HttpClient assets

  • Status: accepted
  • Date: 2026-04-26

Context and Problem Statement

Six large JSON files (36 KB3 MB) were statically imported directly into Angular components and services via TypeScript import statements. This bundled all the data into the main JavaScript bundle, inflating the initial download regardless of whether the user navigated to the HeroWars section. The largest file (hw-guild-raids.json, 3 MB) alone would significantly delay first contentful paint for all users.

Additionally, a seventh file (qcm-bpa.json, 210 KB) was imported but never consumed — the component had switched to a route resolver but the dead import remained.

Decision Drivers

  • Static JSON imports are compiled into the bundle — they cannot be lazy-loaded or cached by the browser independently.
  • Updating the data files required a recompile and redeployment; serving them as assets allows hot-swapping without a rebuild.
  • The HeroWars section is used by a small subset of users; its data should not penalise all other users' load time.

Considered Options

  • Keep static imports
  • Move JSON to assets and load via HttpClient
  • Fetch data from the API backend

Decision Outcome

Chosen option: "Move JSON to assets and load via HttpClient", because it removes the data from the bundle, enables browser-level HTTP caching, and requires no backend changes. The files are not secret (guild-internal analytics data) so serving them as static assets is appropriate.

Structure:

  • JSON files moved from src/files-data/ to src/assets/files-data/
  • HWDataService created at src/app/core/services/herowars/hw-data.service.ts — exposes one readonly observable per file, each piped through shareReplay(1) so the HTTP request fires at most once per app lifecycle
  • HWClanService.loadClan() and HWMemberService.loadMembers() converted from synchronous return values to Observable<T>
  • All consumer components inject HWDataService and subscribe in ngOnInit(); template-called methods that previously accessed guildWarSlots.slots inline now read from a _slots class property populated in the subscribe callback
  • Unused import data from 'src/qcm-bpa.json' and two dead import-helper methods removed from qcm.component.ts

Positive Consequences

  • HeroWars JSON (~4 MB total) no longer shipped in the initial bundle.
  • Each JSON file is independently cacheable by the browser with standard HTTP cache headers.
  • Data files can be updated without recompiling the Angular application.
  • shareReplay(1) ensures a single HTTP request per session even when multiple components subscribe to the same observable.

Negative Consequences

  • Components now initialize asynchronously — there is a brief render before data arrives (consistent with the rest of the app's HTTP-driven components).
  • Object.entries() on any-typed HTTP responses requires explicit Record<string, T> casts to satisfy strict TypeScript, adding minor verbosity.

Pros and Cons of the Options

Keep static imports

  • Good, because synchronous — no async lifecycle complexity.
  • Bad, because adds up to 4 MB to the initial bundle.
  • Bad, because data updates require a full rebuild and redeployment.

Move JSON to assets and load via HttpClient

  • Good, because removes data from the bundle entirely.
  • Good, because browser-cacheable independently of the app JS.
  • Good, because hot-swappable without a recompile.
  • Bad, because converts synchronous service methods to observables, requiring component updates.

Fetch from API backend

  • Good, because data could be managed dynamically via the admin interface.
  • Bad, because requires significant backend work (new endpoints, data model) for data that is currently managed as flat files.
  • Bad, because adds latency and a failure mode not present with local assets.