Saltar al contingut principal
Tornar enrere

FOUC en Astro: Guía Definitiva, Parte I (Script + Config)

#astro #javascript

El FOUC (Flash of Unstyled Content) és un dels problemes que més m’ha costat d’arreglar sempre. És un mal de cap. Ara, en aquest projecte em vaig trobar amb dos nivells de FOUC, i aquí explico com vaig solucionar tots dos.

Nivell 1: El Parpelleig de Color (The White Flash)

El navegador pinta la pàgina en blanc per defecte abans de carregar els teus estils foscos. Solució: Injectar un script “bloquejant” al <head> del Layout principal.

Cal tenir en compte que això a més forma part de la lògica per controlar entre temes clar i fosc en iniciar el lloc.

html
<head>
<script is:inline>
  (function() {
    const theme = localStorage.getItem('theme');
    const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    
    if (theme === 'dark' || (!theme && systemDark)) {
      document.documentElement.classList.add('dark');
      // Injecció directa d'estils per a immediatesa absoluta
      document.documentElement.style.backgroundColor = '#131313';
      document.documentElement.style.colorScheme = 'dark';
    } else {
      document.documentElement.classList.remove('dark');
      document.documentElement.style.backgroundColor = '#ffffff';
       document.documentElement.style.colorScheme = 'light';
    }
  })();
</script>
</head>

Nivell 2: El Salt de Layout (CSS Diferit)

Malgrat l’script, en navegar entre pàgines, els elements es “desmuntaven” per un instant. El culpable: Un plugin d’optimització (@playform/inline) mal configurat.

Aquest plugin fa “inline” del CSS crític, però si es col·loca abans d’altres processos de build a astro.config.mjs, pot causar que el CSS es carregui de forma asíncrona incorrecta, provocant salts. O almenys això em va dir Gemini 3.

Solució: Moure els plugins d’optimització al final de l’array integrations o… el que realment em va solucionar el problema, carregar-me’l.

javascript
export default defineConfig({
// MALAMENT: inline() abans de mdx()
// integrations: [tailwind(), react(), inline(), mdx()],

// BÉ: Optimitzacions al final (o deshabilitades si donen problemes)
integrations: [tailwind(), react(), mdx() /*, inline() */],
});

Aquesta integració injecta CSS a l’HTML, hauria de servir per optimitzar la càrrega, però almenys en el meu cas va ser a costa d’afegir-me aquest FOUC. Per ara la seva eliminació no m’ha afectat en res aparent.

Lliçó: L’estabilitat visual (CLS) és més important que estalviar 2ms de càrrega. Si una optimització trenca l’experiència, fora.