Skip to content

Perf: kezdő állapot beágyazása a kiszolgált HTML-be #69

Description

@Xentinus

Jelenség

A főoldal két, egymás utáni körben tölt be, holott az adat már az elsőben rendelkezésre áll.

  1. A szerver kiszolgálja az index.html-t, és ehhez beolvassa a tartalmat: a MapSpaFallback a PageMetaIndex-ből kéri a kiszolgált oldal címét, leírását és előnézeti képét, a PublicRouteIndex-ből pedig a slug-listát. Mindkettő a ContentCache-en (Redis, mögötte a Postgres) keresztül.

  2. A böngésző letölti a bundle-t, mountolja az appot, és a HomeView onMounted-jében újra elkéri ugyanazt a tartalmat, négy párhuzamos kéréssel:

    const [w, s, e, a] = await Promise.all([
      contentApi.getWorks(),
      contentApi.getSkills(),
      contentApi.getExperiences(),
      contentApi.getAbout(),
    ])

Vagyis a first paint egy teljes API-körrel későbbre tolódik, pedig az adat a HTML kiszolgálásának pillanatában már a szerver kezében volt (vagy egy Redis olvasásra lett volna tőle). Mobil hálózaton ez a kör a látható tartalom megjelenésének a fele.

Javaslat

  1. A SpaShell ágyazza be a főlap kezdő állapotát a kiszolgált HTML-be, <script type="application/json" id="initial-state"> blokkként. Ez adatblokk, nem futtatott szkript, tehát a mai CSP-t (script-src 'self' https://challenges.cloudflare.com) nem érinti — ellentétben egy inline window.__DATA__ = ... értékadással, ami nonce-t vagy hasht igényelne. Ez a különbség a megvalósítás lényegi része.
  2. A content store loadAll()-ja először a beágyazott állapotot próbálja (JSON.parse a DOM-ból), és csak akkor hív API-t, ha nincs vagy nem érvényes. A force = true ág maradjon mindig hálózati.
  3. A beágyazott JSON a works / skills / experiences / about listákat tartalmazza — ugyanazokat a DTO-kat, amiket az API ad, hogy ne legyen két alak. Méret-ellenőrzés kell: a rich text testek nagyok, tehát vagy csak a főlaphoz szükséges mezők kerülnek be (a Desc teljes HTML-je nem), vagy méretkorlát fölött nem ágyazódik be semmi.
  4. A cache-elés a MetaKey mintáját követi: a beágyazandó blokk is a ContentCache egy kulcsa legyen, ugyanazzal az invalidálással — különben minden HTML-kiszolgálás új szerializálás.
  5. A Perf: edge-cache-elt HTML (s-maxage + Cloudflare purge) #58 (edge-cache) ezzel jól illeszkedik: a HTML így tartalmat is hordoz, tehát az edge cache purge-nak pontosnak kell lennie — a s-maxage értékét ennek tudatában kell megválasztani.
  6. Az ArticleView és a TagArchiveView ugyanezt megkapja, ha a beágyazott állapot a kért oldalhoz tartozó tartalmat is hordozza — de a főlap az érdemi nyereség, érdemes ott kezdeni és mérni (LCP előtte/utána).

Érintett fájlok

  • PortfolioCMS.Core/Services/SpaShell.cs
  • PortfolioCMS.Core/Extensions/SpaFallbackExtensions.cs
  • PortfolioCMS.Core/Services/PageMetaIndex.cs, ContentCache.cs
  • portfoliocms.shared/stores/content.ts
  • portfoliocms.client/index.html (a beágyazás helye, a marker mintájára)
  • PortfolioCMS.Tests/SpaShellTests.cs, SpaFallbackTests.cs
  • portfoliocms.shared/stores/__tests__/content.spec.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions