Ich habe das mit Inline-<svg>-Icons geschrieben, um das beste Icon-System zu schaffen. Ich denke immer noch, dass das stimmt. Es ist der einfachste Weg, ein Icon auf eine Seite zu bringen. Kein Netzwerkaufruf, perfekt gestaltbar.
Aber das Inline-Einbetten von Code hat einige Nachteile, einer davon ist, dass es das Caching nicht nutzt. Der Browser muss denselben Code immer wieder lesen und verarbeiten, während Sie herumstöbern. Nicht, dass das eine große Sache wäre. Es gibt viel größere Performance-Probleme zu lösen, oder? Aber es macht immer noch Spaß, über effizientere Muster nachzudenken.
Scott Jehl schrieb, dass nur weil man etwas inline einfügt, heißt das nicht, dass man es nicht cachen kann. Mal sehen, ob Scotts Idee auf SVG-Icons erweiterbar ist.
Beginn mit Inline-SVG
So wie hier...
<!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>
Es ist seltsam einfach, Text als Datei im Browser-Cache abzulegen
Im obigen HTML ruft der Selektor .icon-alarm uns den gesamten SVG-Code für dieses Icon ab.
const iconHTML = document.querySelector(".icon-alarm").outerHTML;
Dann können wir es auf diese Weise im Cache des Browsers ablegen
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'} }
));
}
}
Sehen Sie den Dateipfad /icons/icon-wheelchair.svg? Der ist irgendwie erfunden. Aber er wird tatsächlich an diesem Ort im Cache abgelegt.

Stellen wir sicher, dass der Browser diese Datei aus dem Cache holt, wenn sie angefordert wird
Wir registrieren einen Service Worker auf unseren Seiten
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/sw.js', {
scope: '/'
});
}
Der Service Worker selbst wird ziemlich klein sein, nur ein Cache-Matcher
self.addEventListener("fetch", event => {
let request = event.request;
event.respondWith(
caches.match(request).then(response => {
return response || fetch(request);
})
);
});
Aber... wir fordern diese Datei nie an, weil unsere Icons inline sind.
Stimmt. Aber was, wenn andere Seiten von diesem Cache profitieren würden? Zum Beispiel könnte ein SVG-Icon wie folgt auf der Seite platziert werden
<svg class="icon">
<use xlink:href="/icons/icon-alarm.svg#icon-alarm" />
</svg>
Da /icons/icon-alarm.svg bereit im Cache liegt, wird der Browser es gerne aus dem Cache holen und anzeigen.
(Ich war ziemlich erstaunt, dass das funktioniert. Edge mag <use>-Elemente, die auf Dateien verlinken, nicht, aber das wird bald vorbei sein. Update, es ist vorbei, Edge ist auf Chromium umgestiegen.)
Und selbst wenn die Datei nicht im Cache ist, vorausgesetzt, wir legen diese Datei tatsächlich auf das Dateisystem, ist das wahrscheinlich das Ergebnis einer Art von „Include“ (ich habe Nunjucks im Demo verwendet).
Aber... <use> und Inline-SVG sind nicht ganz dasselbe
Stimmt. Was mir am obigen gefällt, ist, dass es den Cache nutzt und die Icons fast sofort gerendert werden sollten. Und es gibt einige Dinge, die Sie auf diese Weise gestalten können – zum Beispiel sollte das Setzen der Füllung des übergeordneten Icons durch den Shadow DOM gehen, den das <use>-Element erstellt, und die SVG-Elemente darin einfärben.
Dennoch ist es nicht dasselbe. Der Shadow DOM ist eine große Hürde im Vergleich zu Inline-SVG.
Also, verbessern wir sie! Wir könnten ein Skript asynchron laden, das jedes SVG-Icon findet, per Ajax das benötigte SVG abruft und den <use>-Kram ersetzt...
const icons = document.querySelectorAll("svg.icon");
icons.forEach(icon => {
const url = icon.querySelector("use").getAttribute("xlink:href"); // Might wanna look for href also
fetch(url)
.then(response => response.text())
.then(data => {
// This is probably a bit layout-thrashy. Someone smarter than me could probably fix that up.
// Replace the <svg><use></svg> with inline SVG
const newEl = document.createElement("span");
newEl.innerHTML = data;
icon.parentNode.replaceChild(newEl, icon);
// Remove the <span>s
const parent = newEl.parentNode;
while (newEl.firstChild) parent.insertBefore(newEl.firstChild, newEl);
parent.removeChild(newEl);
});
});
Nun, vorausgesetzt, dieser JavaScript-Code wird korrekt ausgeführt, verfügt diese Seite über Inline-SVG, genau wie die ursprüngliche Seite.
Ich habe nicht verstanden, wie es überhaupt in den Cache gelangt ist?
Sie müssen mindestens ein SVG-Icon mit dem Icon inline haben?
Ich hatte noch keine Gelegenheit, dies auszuprobieren, aber die Logik dahinter sieht sehr interessant aus, zumindest bis eine richtige Lösung verfügbar ist. Danke, Chris.
Okay, also was ich aus diesem Artikel mitgenommen habe, ist, die SVG-Sprite-Technik zu verwenden, aber dann JS zu verwenden, um den Inhalt des SVG durch die echten SVG-Daten zu ersetzen.
Das ist genau das, was das svg4everybody Polyfill tut. Es ist als Polyfill gedacht, aber (ich glaube) Sie können die Polyfill-Funktionalität ausschalten, sodass es für alle Browser gilt. (Ich interpretiere die Dokumentation vielleicht falsch).
Ich glaube, ich werde ein Issue im Repo mit einer Funktionsanfrage für dieses Verhalten posten. Ich bin mir nicht sicher, ob es derzeit das tut, was ich denke, dass es tut.
Ich habe eine Funktionsanfrage erstellt. Es sieht jedoch nicht so aus, als ob das Projekt noch gepflegt wird, daher ist es unwahrscheinlich, dass es implementiert wird.
Die einfachste Option ist wahrscheinlich, eine Kopie davon lokal zu speichern und die if-Anweisungen zu entfernen, die auf die Browserunterstützung für externe
<use>prüfen.Hmm, danke, werde das mal ausprobieren. Habe ein Plugin für die Icon-Verwaltung namens IconPress erstellt, bei dem ich nur den Icon-Sprite inline oder per AJAX lade.
Ich hätte lieber externe Sprites verwendet, aber aufgrund von Browser-Inkonsistenzen, wie z. B. der Unmöglichkeit, CSS-Stile innerhalb des Symbols (noch Sprites) hinzuzufügen, habe ich aufgegeben und bin wieder dazu übergegangen, Icons inline einzubetten. Das Problem, das ich beim Inline-Einbetten hatte, war das Caching.
Im Vergleich zur Verwendung von Awesome Fonts, die besser für die Leistung von Websites sind
Ich habe den Performance-Unterschied zwischen Icon-Fonts und Inline-SVG-Icons nicht wirklich getestet, aber ich denke, die Verwendung von Icon-Fonts ist idealer.
Während Inline-SVG-Icons praktisch für die Gestaltung einzelner Elemente innerhalb der Icons sind, trennen sie Präsentation und Inhalt nicht. Mit anderen Worten, dieser SVG-Code existiert im HTML ausschließlich zu Styling-Zwecken, und das ist in gewisser Weise diskussionswürdig.
Meiner Meinung nach ist die Verwendung von CSS-Pseudo-Elementen ::before und ::after zum Rendern von Icon-Fonts ein besserer Ansatz, wenn die Gestaltung einzelner Elemente innerhalb der Icons nicht erforderlich ist (was selten der Fall ist).
Ich nehme an, Sie beziehen sich auf Icon-Fonts wie Font Awesome? Das Problem dabei ist, dass meistens die gesamte Schriftart geladen wird, anstatt nur die für diese Seite benötigten Icons. Das bedeutet, Sie laden Hunderte von Icons, die niemals verwendet werden. Mit einem Inline-SVG laden Sie nur das, was Sie brauchen, nichts anderes. Das ist großartig für die Leistung, und Sie können auch CSS verwenden, um einzelne Teile des SVG zu gestalten (Strich oder Füllung!), während eine Icon-Schriftart die Formen nur mit einer einzigen Farbe füllen kann.
Es ist keine "Plug-and-Play"-Lösung, aber sie ist insgesamt performanter und anpassbarer.
Könnten Sie ein Dokumentfragment anstelle des Spans verwenden?
Das wäre ein großartiger Anwendungsfall für ein benutzerdefiniertes Element. Vielleicht?
Ich denke, das ist der falsche Weg.
Inline-SVG in CSS, und es wird automatisch gecacht und serverseitig komprimiert, wenn aktiviert.
Bitte verwenden Sie das
href-Attribut im BeispielDa
xlink:hrefveraltet ist und dies auch in einem der hier gefundenen Artikel vor einigen Jahren erwähnt wurde