Встроенный SVG… кэшируется

Использование встроенных <svg> — самый простой способ разместить иконку на странице. Нет сетевого запроса, идеально подходит для стилей.

Но у встроенного кода есть недостатки. Один из них – отсутствие  кэширования. Или это можно исправить?

Начнем со встроенного SVG

Как этот…

<!DOCTYPE html>
<html lang="en">

<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>

Легко можно добавить текст в кэш браузера в виде файла

В приведенном ниже HTML-коде селектор .icon-alarm извлекает фрагмент <svg> для иконки.

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

Затем мы сможем вставить его в кэш браузера:

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'} }
    ));
  }
}

Видите путь /icons/icon-wheelchair.svg? Это файл будет помещен в кэш.

Простые, но эффективные советы по кросс-браузерной вёрстке, которые должен знать каждый Удостоверимся, что браузер извлекает этот файл из кэша при запросе

Зарегистрируем Service Worker на страницах:

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

Сам Service Worker будет довольно небольшим:

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

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

Мы никогда не запрашиваем этот файл, потому что наши иконки встроены

Но другие страницы могут извлечь выгоду из этого. Например, SVG-иконка может быть размещена на странице следующим образом:

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

Поскольку /icons/icon-alarm.svg уже готов к кэшированию, браузер просто вытащит его из кэша и отобразит.

Но <use> и встроенный SVG не совсем то же самое

Описанный выше подход использует кэш, а иконки должны отображаться почти сразу. При этом лучше, если установка заливки для родительской иконки будет происходить через shadow DOM, который создает <use>. Поэтому элементы будут «окрашиваться» внутри него. Так что улучшайте это!

Мы могли бы асинхронно загрузить скрипт, который находит каждую иконку, загружает нужные SVG с помощью Ajax и заменяет элементы в <use>…

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

icons.forEach(icon => {
  const url = icon.querySelector("use").getAttribute("xlink:href"); // Мы можем захотеть найти также href
  fetch(url)
    .then(response => response.text())
    .then(data => {
      // Кто-то умнее меня, возможно, сможет это исправить.

      // Заменяем <svg><use></svg> встроенным SVG
      const newEl = document.createElement("span");
      newEl.innerHTML = data;
      icon.parentNode.replaceChild(newEl, icon);

      // Удаляем <span>
      const parent = newEl.parentNode;
      while (newEl.firstChild) parent.insertBefore(newEl.firstChild, newEl);
      parent.removeChild(newEl);
    });
});

Предполагая, что приведенный выше JavaScript-код выполняется правильно, эта страница имеет встроенный SVG, как и оригинальная.

Демо-версии примеров:

  • На Netlify
  • На GitHub

Пожалуйста, оставьте свои комментарии по текущей теме статьи. За комментарии, отклики, подписки, лайки, дизлайки огромное вам спасибо!

Пожалуйста, оставляйте ваши комментарии по текущей теме статьи. За комментарии, отклики, лайки, дизлайки, подписки низкий вам поклон!

Вадим Дворниковавтор-переводчик статьи «Inline SVG… Cached»