SVG en línea frente a externo: el criterio de caché
Qué gana y qué pierde cada modo, la aritmética de la caché frente al peso del documento, el efecto en las métricas de carga, y una tabla de decisión por tipo de gráfico.
La misma imagen puede viajar dentro del HTML o como fichero aparte, y la elección cambia el peso de cada página, lo que se puede estilar, lo que se cachea y cuándo aparece el primer píxel. No hay una respuesta general: hay una aritmética que depende de cuántas veces se repite la imagen, cuántas páginas visita el usuario y si el HTML se cachea. Con esos tres números la decisión es mecánica.
- Enumerar las cuatro formas de incrustar un SVG y sus capacidades.
- Calcular cuándo la caché de un fichero externo compensa la petición extra.
- Anticipar el efecto de cada modo en el primer pintado.
- Aplicar una tabla de decisión a los tipos de gráfico de un proyecto real.
Las cuatro formas
| Modo | Estilable desde la página | currentColor |
Cacheable aparte | Peticiones | Scripts |
|---|---|---|---|---|---|
| En línea | Sí, completo | Sí | No | 0 | Sí |
use externo |
Solo por herencia | Sí | Sí | 1 por sprite | No |
img |
No | No | Sí | 1 por imagen | No |
background-image o mask |
Solo el color con mask |
Solo con mask |
Sí | 1 por imagen | No |
Las capacidades son las que decidirán la mitad de los casos, antes de llegar a la aritmética.
Si necesitas estilar partes del SVG desde CSS, tiene que ser en línea. No hay alternativa.
Si necesitas que el SVG responda a eventos o tenga elementos enfocables, tiene que ser en línea. Un img es una imagen opaca.
Si necesitas que el color se herede del contexto, en línea, use externo, o mask.
Si el SVG es una ilustración grande, decorativa y estática, es una imagen: img con alt="" o background-image.
La aritmética de la caché
Cuando las capacidades no deciden, deciden los números. Tres variables:
S: el peso comprimido del SVG.N: cuántas veces aparece en una misma página.P: cuántas páginas visita un usuario típico en una sesión.
En línea, el coste total es S * N * P si el HTML no se cachea, porque el marcado viaja completo con cada documento.
Externo, el coste es S (una vez, cacheado) más P peticiones condicionales que devuelven respuestas de no modificado, que son unos pocos cientos de bytes cada una. Si la cabecera de caché es inmutable, ni siquiera eso.
El punto de equilibrio es aproximadamente:
en linea gana si: S * N * P < S + coste_de_peticion
Con un icono de 400 bytes comprimidos que aparece 3 veces en una página, y un usuario que ve 5 páginas: en línea son 6 kB; externo son 0,4 kB más una petición. El externo gana en bytes y pierde en latencia (una ida y vuelta antes de que aparezca el icono).
Con una ilustración de 12 kB que aparece una vez en una página que el usuario ve una vez: en línea son 12 kB en el documento; externo son 12 kB en un fichero más una petición. Empate en bytes, y el externo es mejor porque no bloquea el documento y se puede cargar de forma diferida.
Con un icono de 300 bytes que aparece una vez en una página: en línea, sin discusión. La petición cuesta más que el contenido.
La regla que resume la aritmética: por debajo de uno o dos kilobytes y con pocas repeticiones, en línea. Por encima, o con muchas repeticiones en muchas páginas, externo.
El efecto en la carga
Hay un factor que la aritmética de bytes no captura y que a menudo decide.
Un SVG en línea está disponible en el primer pintado. No hay petición, no hay espera, no hay salto. Para el logotipo de la cabecera y para los iconos que aparecen en la primera pantalla, eso es un argumento fuerte: son elementos visibles desde el principio y su ausencia momentánea se nota.
Un SVG externo necesita una ida y vuelta. Si es el elemento más grande de la primera pantalla, se convierte en el candidato a la métrica de mayor renderizado de contenido, y esa métrica mide cuándo aparece. Una ilustración de héroe servida como fichero externo empeora esa métrica frente a la misma en línea.
Pero el SVG en línea engorda el documento, y el documento está en la ruta crítica. Meter 40 kB de ilustraciones en el HTML retrasa el análisis del documento y, con él, todo lo demás.
La síntesis: en línea lo pequeño y visible desde el principio; externo lo grande, y con carga diferida lo que está por debajo del pliegue.
<!-- Grande y por debajo del pliegue -->
<img src="/ilustraciones/proceso.svg" alt="" loading="lazy"
width="600" height="400" decoding="async">
Los atributos width y height no son opcionales: sin ellos, la imagen no reserva espacio y provoca un desplazamiento del contenido cuando llega. Con ellos, el navegador calcula la proporción y deja el hueco.
La tabla de decisión
| Tipo de gráfico | Modo | Motivo |
|---|---|---|
| Icono de interfaz | Sprite en línea o componente | Muchos, pequeños, se estilan |
| Logotipo de la cabecera | En línea | Visible al instante, se estila |
| Logotipo en el pie | En línea, mismo componente | Ya está en el paquete |
| Ilustración de héroe | En línea si es pequeña, externa si supera unos 8 kB | Compromiso entre latencia y peso del documento |
| Ilustración decorativa por debajo del pliegue | img con carga diferida |
No bloquea nada |
| Patrón de fondo | background-image o mask |
No necesita estar en el DOM |
| Gráfico de datos | En línea, generado | Necesita interacción y accesibilidad |
| Gráfico estático de un informe | img con alt descriptivo |
Se cachea y no necesita nada más |
| Diagrama en documentación | En línea | Se estila con el tema y se puede enlazar |
Fíjate en la fila del gráfico de datos y la del gráfico estático. Es el mismo contenido y modos opuestos, y lo que decide no es el peso sino si hay interacción y accesibilidad que preservar.
El argumento contra el SVG en línea es siempre el mismo: no se cachea, así que viaja en cada página. Es cierto y está sobrevalorado, por una razón que casi nadie mide.
Un documento HTML con veinte iconos en línea contiene veinte fragmentos con la misma estructura: los mismos nombres de atributo, los mismos valores de stroke-width, los mismos stroke-linecap, la misma forma de viewBox. Un compresor con ventana suficiente encuentra esa redundancia y la elimina casi entera. El vigésimo icono cuesta una fracción del primero.
En medidas sobre documentos reales, veinte iconos de línea que en bruto ocupan 8 kB acaban aportando entre 1,5 y 2,5 kB al documento comprimido. La estimación ingenua de multiplicar el tamaño de un icono por veinte se equivoca por un factor de tres o cuatro.
Hay dos matices que refuerzan y limitan el argumento. A favor: Brotli con un diccionario compartido mejora todavía más ese caso, porque el patrón se conoce de antemano. En contra: el HTML se descomprime en cada carga, mientras que un fichero cacheado no se vuelve a descargar ni a descomprimir; en un dispositivo lento eso no es gratis.
Y el matiz que más pesa en la práctica: si el HTML se cachea, el debate se acaba. Un sitio estático servido desde un CDN con caché de documento sirve el HTML con sus iconos desde el borde, y la ventaja del fichero externo se reduce a nada.
La conclusión operativa es que la decisión debe basarse en las capacidades (estilado, eventos, accesibilidad) y en el peso absoluto, no en el argumento abstracto de la caché. Y si vas a decidir por la caché, mide el documento comprimido con y sin los iconos en línea antes de decidir. La diferencia real es casi siempre menor de lo que justifica complicar la arquitectura.
Toma la página más pesada de tu sitio y genera dos versiones: con todos los SVG en línea y con todos externos. Mide el tamaño del documento comprimido, el número de peticiones, y el momento del mayor renderizado de contenido en las dos. Después repite la medida simulando una segunda navegación con la caché caliente. Los cuatro números deciden por ti.