# SVG inline... Com cache!

> Inline SVG e estratégias avançadas de cache. Otimize SVG inline com service workers, sprites SVG e técnicas de reutilização eficiente. Otimize agora!

URL: https://dpw.dev/html/inline-svg-cache/  
Publicado em: 2019-06-03  
Categoria: html  
Tags: performance  
Autor: Tárcio Zemel

SVG para ícones é o que há atualmente em webdev. Mas usar SVG inline não nos permite aproveitar as maravilhas do cache... Ou será que isso é possível? 🤔

> Artigo baseado em [original]().

Veja **como usar SVG inline com cache** a unir o que de melhor é possível fazer em sistemas de ícones com SVG cacheados!

## A questão do código inline para ícones em SVG

Muitos desenvolvedores (a maioria?) são a favor de usar **código inline para ícones**. Esta seria a maneira mais fácil de colocar um ícone em uma página: nenhuma requisição extra; perfeitamente estilizado.

Mas código inline tem algumas desvantagens, uma das quais é que não tira proveito do **armazenamento em cache**. O navegador tem que ler e processar o mesmo código tantas vezes quanto forem as visitas às páginas.

Não é tão ruim assim, certo? Certamente, há questões de performance muito mais importantes para nos preocuparmos. Mas, ainda assim, é divertido (neste caso, _importante_) pensar em padrões mais eficientes.

**Scott Jehl** escreveu um artigo mostrando que [só porque você colocou um código inline, não significa que você não possa armazená-lo em cache](https://www.filamentgroup.com/lab/inlining-cache.html). Veremos se a ideia de Scott pode ser aplicada também a ícones SVG.

## Começando com SVG inline

Para começar com essa história toda de **SVG inline com cache**, veja este código de exemplo:

```html
<!doctype html>
<html lang="pt-br">

<head>
  <title>Inline SVG</title>
  <link rel="stylesheet" href="/styles/style.css">
</head>

<body>

  ...

  <svg width="24" height="24" viewBox="0 0 24 24" class="icon icon-alarm" xmlns="http://www.w3.org/2000/svg">
    <path id="icon-alarm" d="M11.5,22C11.64,22 11.77,22 11.9,21.96C12.55,21.82 13.09,21.38 13.34,20.78C13.44,20.54 13.5,20.27 13.5,20H9.5A2,2 0 0,0 11.5,22M18,10.5C18,7.43 15.86,4.86 13,4.18V3.5A1.5,1.5 0 0,0 11.5,2A1.5,1.5 0 0,0 10,3.5V4.18C7.13,4.86 5,7.43 5,10.5V16L3,18V19H20V18L18,16M19.97,10H21.97C21.82,6.79 20.24,3.97 17.85,2.15L16.42,3.58C18.46,5 19.82,7.35 19.97,10M6.58,3.58L5.15,2.15C2.76,3.97 1.18,6.79 1,10H3C3.18,7.35 4.54,5 6.58,3.58Z"></path>
  </svg>
```

Uma parte de uma página HTML comum, sem mistério. No `<body>`, a peça principal de nossa investigação, um SVG inline.

## Como cachear SVG inline como um arquivo

No HTML acima, o seletor `.icon-alarm` provê o pedaço (_chunk_) inteiro de `<svg>` para aquele ícone.

```javascript
const iconHTML = document.querySelector(".icon-alarm").outerHTML;
```

Então, torna-se possível colocar isso no cache do navegador assim:

```javascript
if ("caches" in window) {
  caches.open('static').then(function(cache) {
    cache.put("/icons/icon-wheelchair.svg", new Response(
      iconHTML,
      { headers: {'Content-Type': 'image/svg+xml'} }
    ));
  }
}
```

Vê o caminho `/icons/icon-wheelchair.svg`? Isso é meio que apenas inventado. Mas realmente será colocado no cache naquele local (_location_).

![SVG inline com cache: DevTools mostrando recurso.](/images/blog/inline-svg-cache/inline-svg-cache-arquivo-svg-devtools.webp)

## Garantindo que o navegador use esse arquivo sem cache corretamente

Para o macete de usar SVG inline com cache dê certo, também é preciso registrar um Service Worker para as páginas:

```javascript
if (navigator.serviceWorker) {
  navigator.serviceWorker.register('/sw.js', {
    scope: '/'
  });
}
```

Que é bem pequeno, na verdade, servindo apenas como um correspondente de cache (_cache matcher_):

```javascript
self.addEventListener("fetch", event => {
  let request = event.request;

  event.respondWith(
    caches.match(request).then(response => {
      return response || fetch(request);
    })
  );
});
```

## Mas... Esse arquivo SVG nunca é requisitado, já que é inline!

Essa afirmação é verdade, mas e se outras páginas também se beneficiassem desse cache?

Por exemplo, um ícone SVG poderia ser colocado na página assim:

```html
<svg class="icon">
  <use xlink:href="/icons/icon-alarm.svg#icon-alarm" />
</svg>
```

Uma vez que `/icons/icon-alarm.svg` está pronto para ser colocado em cache, o navegador irá arrancá-lo do cache e exibí-lo.

> **Nota:** Como algo totalmente inesperado (#sqn), o Edge não gosta de elementos `<use>` que se vinculam a arquivos (mas, teoricamente, isso deve ser resolvido em breve).

## Mas… `<use>` e inline SVG não são exatamente a mesma coisa

E há algumas coisas possíveis de serem estilizadas dessa maneira — por exemplo, definir o `fill` do ícone-pai faz passar para Shadow DOM que o `<use>` cria e colore os elementos SVG dentro dele.

Ainda assim, realmente não é a mesma coisa. Shadow DOM é uma grande barreira em comparação a SVG inline.

É possível, por exemplo, carregar de forma assíncrona um script que encontre cada ícone SVG, usa um Ajax para o SVG necessário e substitui o `<use>`...

```javascript
const icons = document.querySelectorAll("svg.icon");

icons.forEach(icon => {
  const url = icon.querySelector("use").getAttribute("xlink:href");
  fetch(url)
    .then(response => response.text())
    .then(data => {
      // Isso provavelmente pode atrapalhar um pouco o layout (layout-thrashy).
      // Algum nerd do JavaScript poderia consertar isso e enviar pra gente. <3

      // Troca o <svg><use></svg> por inline SVG
      const newEl = document.createElement("span");
      newEl.innerHTML = data;
      icon.parentNode.replaceChild(newEl, icon);

      // Remove os <span>s
      const parent = newEl.parentNode;
      while (newEl.firstChild) parent.insertBefore(newEl.firstChild, newEl);
      parent.removeChild(newEl);
    });
});
```

Agora, supondo que esse JavaScript seja executado corretamente, essa página tem o SVG inline disponível da mesma forma que a página original! ❤

## Conclusão sobre SVG inline com cache!

Como visto, **é possível sim usar inline SVG com cache**!

Claro, adaptações e criações em código devem ser feitas e algumas tecnologias novas usadas, mas nada que seja absurdamente difícil.

Certamente, para os casos em que seja preciso usar sistemas de ícones em SVG com código inline, esta técnica está em alta consideração.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
