Přejít na obsah
DVERSE

View Transitions v produkci

Poznámky k shared-element přechodům na statickém Workeru

Astro nabízí View Transitions jako API první třídy. Stačí deklarovat viewTransitionName na dvou prvcích v různých trasách a prohlížeč mezi nimi automaticky animuje přechod — žádná JavaScriptová knihovna pro animace není potřeba.

Nasazení na Cloudflare Workers se Static Assets ale přineslo pár zádrhelů, které stojí za to zdokumentovat.

Nastavení

Portfolio běží na Astro 6 s output: "static". Každá stránka je předrenderována při sestavení a servírována z Cloudflare edge jako prostý HTML soubor. Jediná dynamická trasa je /api/brief, obsluhovaná Workerem.

View Transitions žijí čistě v prohlížeči — server o nich neví. To je ta dobrá část.

Jak funguje morf

Dva prvky sdílejí společný view-transition-name:

<!-- PostCard.astro (stránka indexu) -->
<h3 style={{ viewTransitionName: `thought-${slug}-title` }}>
  {title}
</h3>
<!-- [slug].astro (stránka příspěvku) -->
<h1 style={{ viewTransitionName: `thought-${slug}-title` }}>
  {title}
</h1>

Při navigaci mezi nimi prohlížeč zachytí snímky obou prvků a plynule morfuje jeden do druhého. Žádný Motion, žádný FLIP — čistý CSS pod kapotou.

Záludnosti

Tři věci nás kously při nasazení:

  1. Duplicitní názvy přechodů — pokud dvě karty na indexu sdílejí stejný název, prohlížeč tiše zahodí přechod. Každý název musí být na stránce unikátní.
  2. MPA vs SPA režim — Astro standardně používá MPA přechody (plné načtení stránky). Komponenta <ViewTransitions /> přepíná na zachycování navigace ve stylu SPA.
  3. Cachování Cloudflare — Workers agresivně cachují. Zastaralá HTML odpověď může odkazovat na starý název přechodu, který už na cílové stránce neexistuje.

Řešení problému s cache

Přidali jsme Cache-Control: no-cache pro HTML odpovědi, zatímco statické assety (JS, CSS, obrázky) zůstávají na dlouhodobém cache:

// Worker fetch handler
export default {
  async fetch(request: Request, env: Env) {
    const response = await env.ASSETS.fetch(request);
    const url = new URL(request.url);

    if (url.pathname.endsWith("/") || url.pathname.endsWith(".html")) {
      const headers = new Headers(response.headers);
      headers.set("Cache-Control", "no-cache");
      return new Response(response.body, { ...response, headers });
    }

    return response;
  },
};

To není specifické pro View Transitions — je to dobrá praxe pro jakýkoliv statický web, kde se HTML mění při každém nasazení, ale assety jsou hashované.

Poznámky k výkonu

View Transitions přidávají nula kilobajtů JavaScriptu při použití vestavěné podpory Astra. Prohlížečové API document.startViewTransition() zvládne vše.

Měřili jsme pomocí Lighthouse na reprezentativní stránce příspěvku:

MetrikaPředPo
Performance9898
FCP0.8s0.8s
LCP1.1s1.1s
CLS00

Žádná regrese. Samotný přechod přidává vnímanou prodlevu ~250ms (doba morfu), ale uživatelé to vnímají jako záměrnou animaci, nikoliv jako dobu načítání.

Reduced motion

Přechody respektují prefers-reduced-motion. Když má uživatel aktivované omezení pohybu, Astro se vrátí k okamžitému prolínání — stále lepší než tvrdá výměna stránky, ale bez plynulých morfů.


Kompletní implementace žije v šabloně příspěvku a komponentě PostCard. Vzor se zobecňuje na jakoukoliv dvojici tras se sdíleným obsahem — případové studie používají stejný přístup.