You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
A böngésző letölti a bundle-t, mountolja az appot, és a HomeViewonMounted-jében újra elkéri ugyanazt a tartalmat, négy párhuzamos kéréssel:
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
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.
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.
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.
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.
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.
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).
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.
A szerver kiszolgálja az
index.html-t, és ehhez beolvassa a tartalmat: aMapSpaFallbackaPageMetaIndex-ből kéri a kiszolgált oldal címét, leírását és előnézeti képét, aPublicRouteIndex-ből pedig a slug-listát. Mindkettő aContentCache-en (Redis, mögötte a Postgres) keresztül.A böngésző letölti a bundle-t, mountolja az appot, és a
HomeViewonMounted-jében újra elkéri ugyanazt a tartalmat, négy párhuzamos kéréssel: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
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 inlinewindow.__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.contentstoreloadAll()-ja először a beágyazott állapotot próbálja (JSON.parsea DOM-ból), és csak akkor hív API-t, ha nincs vagy nem érvényes. Aforce = trueág maradjon mindig hálózati.works/skills/experiences/aboutlistá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 (aDescteljes HTML-je nem), vagy méretkorlát fölött nem ágyazódik be semmi.MetaKeymintáját követi: a beágyazandó blokk is aContentCacheegy kulcsa legyen, ugyanazzal az invalidálással — különben minden HTML-kiszolgálás új szerializálás.s-maxageértékét ennek tudatában kell megválasztani.ArticleViewés aTagArchiveViewugyanezt 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.csPortfolioCMS.Core/Extensions/SpaFallbackExtensions.csPortfolioCMS.Core/Services/PageMetaIndex.cs,ContentCache.csportfoliocms.shared/stores/content.tsportfoliocms.client/index.html(a beágyazás helye, a marker mintájára)PortfolioCMS.Tests/SpaShellTests.cs,SpaFallbackTests.csportfoliocms.shared/stores/__tests__/content.spec.ts