Files
HealthLog/src/lib/intl/formatter-cache.ts
T
Marc-André Bombeck 80bbf2ba3b perf(ui): harden theme-provider hydration seam + cache per-row Intl formatters
Theme provider now initializes to the SSR-stable default and reconciles
the stored preference in a mount effect instead of reading localStorage
in the useState initializer — closes the same React #418 hydration seam
the sidebar already fixed (the inline script still handles the pre-paint
class, so no FOUC). Add a process-wide Intl formatter cache and route the
per-row workout/medication list helpers through it so a formatter is
constructed once per (locale, options) rather than once per row per
render.
2026-07-08 23:48:24 +02:00

45 lines
1.6 KiB
TypeScript

/**
* Process-wide cache for `Intl.NumberFormat` / `Intl.DateTimeFormat`
* instances, keyed by locale + options.
*
* Constructing an `Intl.*` formatter is comparatively expensive; several
* list-item helpers built one per row per render (`workout-list`,
* `recent-workouts-tile`, `medication-card`, …). These getters return a cached
* instance so the construction cost is paid once per distinct (locale, options)
* shape instead of once per call. Formatters are immutable + stateless, so
* sharing a single instance across calls is safe.
*
* Keyed by `locale + "" + JSON.stringify(options)`; stringifying the
* (tiny, literal) options object per call is orders of magnitude cheaper than
* a formatter construction. The set of distinct shapes is bounded and small,
* so the cache never needs eviction.
*/
const numberFormatters = new Map<string, Intl.NumberFormat>();
const dateTimeFormatters = new Map<string, Intl.DateTimeFormat>();
export function getNumberFormat(
locale: string,
options: Intl.NumberFormatOptions,
): Intl.NumberFormat {
const key = `${locale}${JSON.stringify(options)}`;
let fmt = numberFormatters.get(key);
if (!fmt) {
fmt = new Intl.NumberFormat(locale, options);
numberFormatters.set(key, fmt);
}
return fmt;
}
export function getDateTimeFormat(
locale: string,
options: Intl.DateTimeFormatOptions,
): Intl.DateTimeFormat {
const key = `${locale}${JSON.stringify(options)}`;
let fmt = dateTimeFormatters.get(key);
if (!fmt) {
fmt = new Intl.DateTimeFormat(locale, options);
dateTimeFormatters.set(key, fmt);
}
return fmt;
}