Kostenloses Bild-CDN: GitHub Pages & JS
Die schnelle Auslieferung optimierter Bilder ist entscheidend für die Web-Performance. Kommerzielle CDNs bieten zwar robuste Lösungen, doch kleine öffentliche Projekte können GitHub Pages für statisches Bild-Hosting und jsDelivr für die gecachte Auslieferung von Repository-Assets nutzen. Keiner der beiden Dienste optimiert diese Bilder automatisch.
Bild-CDNs verstehen
Ein Bild-CDN (Content Delivery Network) cacht Bilder und liefert sie von Servern aus, die geografisch näher bei den Nutzern liegen, was die Ladezeiten deutlich verbessert. Die Optimierung von Bildern über ein CDN reduziert die Bandbreite, verbessert das SEO und steigert die gesamte Web-Performance.
GitHub Pages einrichten
GitHub Pages bietet kostenloses statisches Hosting direkt aus Ihren GitHub-Repositories:
-
Erstellen Sie ein GitHub-Repository mit dem Namen
image-cdn. -
Klonen Sie das Repository lokal:
git clone https://github.com/your-username/image-cdn.git cd image-cdn -
Erstellen Sie einen Ordner
imagesund fügen Sie Ihre Bilder hinzu. -
Committen und pushen Sie Ihre Änderungen:
git add images git commit -m "Add initial images" git push origin main -
Aktivieren Sie GitHub Pages in den Einstellungen Ihres Repositories und wählen Sie den Branch
mainals Quelle aus.
Ihre Bilder sind nun über
https://your-username.github.io/image-cdn/images/your-image.jpg erreichbar.
Einschränkungen von GitHub Pages
Beachten Sie die Einschränkungen von GitHub Pages:
- Weiches Bandbreitenlimit von 100 GB pro Monat.
- Größenlimit von 1 GB für die veröffentlichte Website, bei einem empfohlenen Limit von 1 GB für das Quell-Repository.
- Keine integrierte Bildverarbeitung.
- Die Standarddomain von GitHub Pages kann in manchen Unternehmensumgebungen blockiert sein.
Nutzen Sie dieses Setup für Assets kleiner öffentlicher Projekte, nicht für private Uploads oder einen kommerziellen Bild-Hosting-Dienst. GitHub Pages schränkt kommerzielle Transaktionen und SaaS-Hosting ein. Prüfen Sie die Nutzungslimits sowie die Nutzungsrichtlinie von jsDelivr, bevor Sie sich auf einen der beiden Dienste verlassen.
Ein JavaScript-CDN einbinden
Nutzen Sie einen CDN-Dienst wie jsDelivr, um Assets aus öffentlichen Repositories zu cachen. Es handelt sich nicht um eine JavaScript-Bibliothek, die Sie installieren, und der Dienst nimmt für Sie keine Größenänderung von Bildern vor.
Binden Sie Ihre Bilder über jsDelivr ein:
<img
src="https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/your-image.jpg"
alt="Optimized Image"
/>
Fixieren Sie in der URL ein Release-Tag oder einen Commit, um ein vorhersehbares Caching zu
erreichen, zum Beispiel https://cdn.jsdelivr.net/gh/your-username/image-cdn@v1.0.0/images/your-image.jpg, nachdem Sie dieses Tag erstellt
haben. Aktualisieren Sie die Version, wenn sich Bilder ändern.
Zuverlässigkeit und Fallback
jsDelivr bietet zwar hervorragende Performance, implementieren Sie dennoch Fallback-Strategien:
function loadImage(imageElement, primarySrc, fallbackSrc) {
imageElement.onerror = function () {
imageElement.onerror = null
console.warn('Primary CDN failed, using fallback')
imageElement.src = fallbackSrc
}
imageElement.src = primarySrc
}
const img = document.getElementById('my-image')
if (!(img instanceof HTMLImageElement)) throw new Error('Missing image element: my-image')
loadImage(
img,
'https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image.jpg',
'https://your-username.github.io/image-cdn/images/image.jpg',
)
Fügen Sie ein Element <img id="my-image" alt="..."> mit passendem Alternativtext hinzu, bevor Sie
diesen Code ausführen. Wenn beide Ursprünge fehlschlagen, behält der Browser den Alternativtext des
Bildes bei, anstatt den Fallback endlos erneut zu versuchen.
Automatisierung mit GitHub Actions
Automatisieren Sie die Bildoptimierung und das Deployment mit GitHub Actions:
Erstellen Sie .github/workflows/compress-images.yml:
name: Compress Images
on:
pull_request:
paths:
- '**.jpg'
- '**.jpeg'
- '**.png'
- '**.webp'
jobs:
build:
if: github.event.pull_request.head.repo.full_name == github.repository
name: calibreapp/image-actions
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Compress Images
uses: calibreapp/image-actions@26d5b54006db4da7a1b29903f33404a6f77b58cf
Dieser Workflow optimiert Bilder bei Pull Requests aus demselben Repository und kann Änderungen committen sowie eine Zusammenfassung posten. Pull Requests aus Forks sind bewusst ausgenommen. Prüfen Sie die Action, bevor Sie den fixierten Commit aktualisieren; siehe ihre Konfiguration.
Eigene Optimierung implementieren
Für mehr Kontrolle installieren Sie sharp in einem Projekt mit Node.js 22 oder neuer und speichern Sie dies als optimize.cjs.
Legen Sie die Quellbilder in original-images/ ab und führen Sie node optimize.cjs aus. Die Ausgaben landen in einem
separaten Verzeichnis; vorhandene Dateien werden dort ersetzt. Die Qualitätseinstellungen für JPEG
und WebP sind verlustbehaftet, und wenn Sie für PNG quality setzen, aktiviert das die
Paletten-Quantisierung, bei der ebenfalls Farben verloren gehen können:
const sharp = require('sharp')
const fs = require('fs').promises
const path = require('path')
async function optimizeImage(inputPath, outputPath) {
try {
const image = sharp(inputPath)
const metadata = await image.metadata()
const config = {
jpeg: { quality: 80, progressive: true },
png: { quality: 80, compressionLevel: 9 },
webp: { quality: 80 },
}
switch (metadata.format) {
case 'jpeg':
await image.jpeg(config.jpeg).toFile(outputPath)
break
case 'png':
await image.png(config.png).toFile(outputPath)
break
case 'webp':
await image.webp(config.webp).toFile(outputPath)
break
default:
throw new Error(`Unsupported format: ${metadata.format}`)
}
console.log(`Optimized: ${path.basename(inputPath)}`)
return outputPath
} catch (error) {
console.error(`Failed to optimize ${inputPath}:`, error)
throw error
}
}
async function processDirectory(inputDir, outputDir) {
try {
await fs.mkdir(outputDir, { recursive: true })
const files = await fs.readdir(inputDir)
for (const file of files) {
const inputPath = path.join(inputDir, file)
const outputPath = path.join(outputDir, file)
const stat = await fs.stat(inputPath)
if (stat.isFile() && /\.(jpe?g|png|webp)$/i.test(file)) {
await optimizeImage(inputPath, outputPath)
}
}
console.log('All images processed successfully')
} catch (error) {
console.error('Directory processing failed:', error)
throw error
}
}
processDirectory('original-images', 'optimized-images').catch(() => {
process.exitCode = 1
})
Ihr Setup testen
Überprüfen Sie Ihr CDN:
-
Browser-Entwicklertools: Prüfen Sie das Netzwerk-Panel.
-
Tools für Performance-Tests:
-
Monitoring echter Nutzer: Nutzen Sie die Performance-API:
document.addEventListener('DOMContentLoaded', () => { window.addEventListener('load', () => { const imageEntries = performance .getEntriesByType('resource') .filter((entry) => entry.initiatorType === 'img') const totalLoadTime = imageEntries.reduce((sum, entry) => sum + entry.duration, 0) if (imageEntries.length === 0) return const avgLoadTime = totalLoadTime / imageEntries.length console.log(`Average image load time: ${avgLoadTime.toFixed(2)}ms`) imageEntries.forEach((entry) => { console.log(`${entry.name}: ${entry.duration.toFixed(2)}ms`) }) }) })
Sicherheit
Setzen Sie diese Sicherheitsmaßnahmen um:
CORS-Header
GitHub Pages verwendet keine Datei _headers, um HTTP-Response-Header zu konfigurieren. Prüfen Sie die
tatsächlichen Response-Header mit curl -I und nutzen Sie einen Hoster mit konfigurierbaren Headern,
wenn Ihre Anwendung eine eigene CORS- oder Cache-Richtlinie benötigt. CORS steuert den Zugriff von
Skripten auf die Bytes der Response; es ist keine Authentifizierung und verhindert das gewöhnliche
Einbetten von Bildern nicht.
Hotlinking verhindern
Clientseitiges JavaScript kann nicht verhindern, dass eine andere Website öffentliche Bild-URLs einbettet. Wenn Zugriffskontrolle oder Traffic-Limits wichtig sind, nutzen Sie einen Anbieter, der signierte URLs oder eine andere serverseitige Richtlinie durchsetzt. Speichern Sie keine privaten oder sensiblen Bilder in diesem öffentlichen Repository.
Fortgeschrittene Optimierung
Responsive Bilder
<img
srcset="
https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image-small.jpg 480w,
https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image-medium.jpg 800w,
https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image-large.jpg 1200w
"
sizes="(max-width: 600px) 480px,
(max-width: 1200px) 800px,
1200px"
src="https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image-large.jpg"
alt="Responsive Image"
loading="lazy"
/>
Moderne Bildformate
Verwenden Sie ein System zur Formaterkennung und für Fallbacks:
<picture>
<source
srcset="https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image.avif"
type="image/avif"
/>
<source
srcset="https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image.webp"
type="image/webp"
/>
<img
src="https://cdn.jsdelivr.net/gh/your-username/image-cdn/images/image.jpg"
alt="Optimized image with format fallbacks"
loading="lazy"
/>
</picture>
Vorteile und Einschränkungen
Vorteile:
- Keine Hosting-Kosten für kleine öffentliche Projekte im Rahmen der Nutzungsrichtlinien der Anbieter.
- Einfache Einrichtung und Automatisierung.
- Verbesserte globale Performance.
Einschränkungen:
- GitHub Pages hat ein weiches Bandbreitenlimit von 100 GB/Monat und ein Limit von 1 GB für die veröffentlichte Website.
- Weniger Kontrolle im Vergleich zu kommerziellen CDNs.
- Keine integrierte Bildtransformation.
Für größere Projekte oder fortgeschrittene Anforderungen sollten Sie Dienste wie Transloadits Bildverarbeitungs-API in Betracht ziehen.
Mit diesen Schritten haben Sie ein kostenloses Bild-CDN mit GitHub Pages, einem JavaScript-CDN und GitHub Actions erstellt.
