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

Встроенные 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»

Комментарии

Оставьте свой комментарий
Пока никто не оставил комментариев