Inline SVG… Bufret

0
26

Jeg skrev at bruk av inline <svg> ikoner som gjør det til det beste ikonet system. Jeg tror fortsatt det er sant. Det er den enkleste måten å slippe et ikon på en side. Ingen forespørsel til nettverket om, perfekt styleable.

Men inlining code har noen ulemper, og en av disse er at det ikke dra nytte av caching. Du gjør leseren lese og behandle den samme koden over og over som du bla rundt. Ikke så stor av en avtale. Det er mye større ytelse fisk til yngel, ikke sant? Men det er fortsatt morsomt å tenke mer effektiv mønstre.

Scott Jehl skrev at bare fordi du inline det er noe som ikke bety at du ikke kan cache det. La oss se om Scotts idé kan utvide til SVG-ikoner.

Starter med inline SVG

Som dette…

<!DOCTYPE html>
<html lang=”no”>

<head>
<title>Inline SVG</title>
<link rel=”stylesheet” href=”/stiler/stil.css”>
</head>

<body>

<svg width=”24″ høyde=”24″ viewBox=”0 0 24 24″ class=”icon ikon-alarm” xmlns=”http://www.w3.org/2000/svg”>
<bane 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.58 Z”></bane>
</svg>

Det er nifs lett å kaste tekst i hurtigbufferen til nettleseren som en fil

I over HTML, velgeren .ikon-alarm vil hente oss i en hel del av <svg> for at ikonet.

const iconHTML = – dokument.querySelector(“.ikon-alarm”).outerHTML;

Da kan vi plunk den inn i nettleserens cache som dette:

hvis (“cacher” i vinduet) {
cacher.åpne(‘statisk’).deretter(function(cache) {
cache.sette(“/ikoner/ikon-rullestol.svg”, nye Svar(
iconHTML,
{ overskrifter: {‘Content-Type’: ‘image/svg+xml’} }
));
}
}

Se filbanen /ikoner/ikon-rullestol.svg? Det er ganske nettopp gjort opp. Men det virkelig vil bli satt i buffer på dette stedet.

La oss sørge for at leseren griper at filen ut av buffer når det er bedt om

Vi vil registrere en Service Arbeidstaker på våre sider:

hvis (navigator.serviceWorker) {
navigator.serviceWorker.registrer deg(‘/sw.js’, {
omfang: ‘/’
});
}

Tjenesten arbeidstaker i seg selv vil være ganske liten, bare en buffer brudd:

selvet.addEventListener(“hente”, event => {
la forespørsel = event.forespørsel;

event.respondWith(
cacher.match(på forespørsel).deretter(svar => {
tilbake respons || hent(avtale);
})
);
});

Men… vi aldri vil be om at filen, fordi våre ikoner er innebygd.

Sant. Men hva om andre sider har dratt nytte av som buffer? For eksempel, en SVG-ikonet kan være plassert på den side som dette:

<svg class=”icon”>
<bruk xlink:href=”/ikoner/ikon-alarm.svg#ikon-alarm” />
</svg>

Siden /ikoner/ikon-alarm.svg sitter der klar i cache, nettleseren vil gjerne plukke den ut av cache og vise det.

(Jeg var litt overrasket over dette fungerer. Kant ikke liker <bruk> – elementer som har en link til filer, men det vil være over snart nok.)

Og selv om filen ikke er i cache, forutsatt at vi faktisk chuck denne filen på fil-system sannsynlig et resultat av en slags “inkluderer” (jeg brukte Nunjucks på demo).

Men… <bruk> og inline SVG ikke er helt det samme

Sant. Hva jeg liker med dette er at det er å gjøre bruk av cache og ikonene skal gjengi nær umiddelbart. Og det er noen ting du kan style på denne måten — for eksempel å sette fylle på foreldre-ikonet skal gå gjennom skyggen DOM som <bruker> oppretter og fargelegge SVG-elementer innenfor.

Likevel, det er ikke det samme. Skyggen DOM er en stor barriere i forhold til inline SVG.

Så, forbedre dem! Vi kunne asynkront laste inn et script som finner hver SVG-ikonet, Ajaxs for SVG-det er behov for, og erstatter <bruk> ting…

const ikoner = – dokument.querySelectorAll(“svg.ikonet”);

ikoner.forEach(ikonet => {
const url = – ikonet.querySelector(“bruker”).getAttribute(“xlink:href”); // Kan gjerne se for href også
hente(url)
.deretter(svar => svar.tekst())
.deretter(data => {
// Dette er trolig en bit layout-thrashy. Noen er smartere enn meg kan sikkert fikse det opp.

// Erstatt <svg><bruker></svg> med inline SVG
const newEl = – dokument.createElement(“span”);
newEl.innerHTML = data;
ikonet.parentNode.replaceChild(newEl, ikon);

// Fjerne <span>s
const forelder = newEl.parentNode;
mens (newEl.firstChild) forelder.insertBefore(newEl.firstChild, newEl);
forelder.removeChild(newEl);
});
});

Nå, forutsatt at denne JavaScript kjører på riktig måte, denne siden har inline SVG tilgjengelig akkurat som den opprinnelige siden gjorde.

Demo & Repo

  • Demo på Netlify
  • Repo på GitHub