Improving web interface responsiveness often starts with optimizing how your frontend communicates with the backend. In our Vue.js-basierten Semaphore UI haben wir mehrere Techniken eingeführt, um das Laden von Daten für die Benutzer schneller und reibungsloser zu gestalten. Dieser Beitrag teilt die drei wirkungsvollsten Änderungen, die wir in Version 2.14 implementiert haben.
Warum API-Nutzung optimieren?
APIs sind oft das Rückgrat dynamischer Webanwendungen, aber schlecht verwaltete Anfragen können Engpässe verursachen. Lange Wartezeiten bei sequenziellen Aufrufen oder redundantes Abrufen von Daten verschlechtern die Benutzererfahrung. Lassen Sie uns diese Probleme direkt angehen.
1. Parallele Anfragen mit Promise.all()
Das Problem: Sequenzielle Anfragen
Eine häufige Falle ist es, API-Aufrufe nacheinander zu machen. Zum Beispiel, zuerst Benutzerdaten abzurufen, dann deren Bestellungen, dann deren Präferenzen:
// Sequenzieller Ansatz (langsam 😞)
async function fetchData() {
const user = await getUser();
const inventory = await getInventory(projectID);
const templates = await getTemplates(projectID);
return { user, inventory, templates };
}
Hier wartet jede Anfrage, bis die vorherige abgeschlossen ist. Wenn jeder Aufruf 200 ms dauert, beträgt die Gesamtdauer 600 ms—eine spürbare Verzögerung.
Die Lösung: Parallele Ausführung
Vue.js nutzt die asynchronen Fähigkeiten von JavaScript, sodass wir mehrere Anfragen gleichzeitig mit Promise.all()
auslösen können:
// Paralleler Ansatz (schnell ⚡)
async function fetchDataParallel() {
const [user, inventory, templates] = await Promise.all([
getUser(),
getInventory(projectID),
getTemplates(projectID),
]);
return { user, inventory, templates };
}
Durch das Gruppieren unabhängiger Anfragen werden alle drei Aufrufe gleichzeitig aufgelöst. Wenn jeder 200 ms dauert, sinkt die Gesamtdauer auf 200 ms!
Integration mit Vue
In einer Vue-Komponente verwenden Sie dieses Muster in Lebenszyklus-Hooks oder Methoden:
export default {
props: {
projectID: Number,
},
watch: {
async projectID() {
await this.fetchDataParallel();
},
},
async created() {
await this.fetchDataParallel();
},
methods: {
async fetchDataParallel() {
try {
const [
this.user,
this.inventory,
this.templates
] = await Promise.all([
getUser(),
getInventory(this.projectID),
getTemplates(this.projectID),
]);
} catch (error) {
console.error("Fehler beim Laden der Daten:", error);
}
};
}
Tipp: Kombinieren Sie dies mit Skeleton-Loadern, um die Benutzer während des Ladevorgangs zu beschäftigen.
2. Wiederverwendung von zwischengespeicherten API-Antworten
Das Problem: Redundantes Abrufen
Apps rufen oft dieselben Daten in verschiedenen Komponenten erneut ab (z. B. Benutzerdaten, die von mehreren Ansichten angefordert werden). Dies verschwendet Bandbreite und verlangsamt die Benutzeroberfläche.
Die Lösung: Zwischenspeichern und Wiederverwenden
Speichern Sie API-Antworten und verwenden Sie sie, bis sie ungültig werden. Das Reaktivitätssystem von Vue macht dies einfach mit einem zentralen Store (wie Pinia oder Vuex):
Schritt 1: Erstellen Sie einen Cache-Store
// stores/apiCache.js
import { defineStore } from 'pinia';
export const useApiCache = defineStore('apiCache', {
state: () => ({
project: null,
templates: {},
}),
actions: {
async fetchProject() {
if (!this.project) {
this.project = await getProject();
}
return this.project;
},
async fetchTemplates(id) {
if (!this.templates[id]) {
this.templates[id] = await fetchTemplates(id);
}
return this.templates[id];
},
},
});
Schritt 2: Verwenden Sie den Store in Komponenten
// Component.vue
import { useApiCache } from '@/stores/apiCache';
export default {
setup() {
const apiCache = useApiCache();
// Wiederverwendet zwischengespeicherten Benutzer oder ruft einmal ab
const user = apiCache.fetchUser();
return { user };
},
};
Tipp: In Semaphore UI verwenden wir noch kein Pinia, planen jedoch bald die Migration.
Strategien zur Ungültigmachung des Caches
- Zeitbasierte Ablauffrist: Löschen Sie zwischengespeicherte Daten nach einer festgelegten Dauer.
- Manuelle Auslöser: Ungültigmachen nach Mutationen (z. B. wenn ein Benutzer sein Profil aktualisiert).
- Reaktivität von Vue: Setzen Sie Daten zurück, wenn sich der Zustand der App ändert (z. B. beim Ausloggen).
3. Verwendung von Skeleton-Loadern für reibungslosere Übergänge
Das Problem: Unresponsive UI während des Ladens
Selbst mit optimierten API-Aufrufen stehen Benutzer während des Ladens von Daten vor kurzen Verzögerungen. Leere Bildschirme oder eingefrorene Oberflächen während dieser Zeit können Ihre App unpoliert oder langsam erscheinen lassen, selbst wenn die tatsächliche Abrufzeit minimal ist.
Die Lösung: Skeleton-Loader
Skeleton-Platzhalter ahmen das Layout Ihrer Inhalte nach, während Daten geladen werden, und bieten visuelles Feedback, das die Benutzer beschäftigt hält. In Kombination mit parallelen Anfragen und Caching schaffen sie eine nahtlose Wahrnehmung von Geschwindigkeit.
So fügen Sie Skeleton-Loader in Vue.js hinzu
Schritt 1: Wählen Sie die Skeleton-Komponente
In Semaphore UI verwenden wir das Vuetify-Framework. Es enthält bereits eine Skeleton-Loader-Komponente.
<v-skeleton-loader
type="
table-heading,
image,
list-item-two-line,
list-item-two-line,
list-item-two-line"
></v-skeleton-loader>
Schritt 2: Integrieren Sie mit asynchronem Datenabruf Verwenden Sie einen Ladezustand, um zwischen Skeletons und echtem Inhalt umzuschalten:
// Component.vue
export default {
data() {
return {
isLoading: true,
user: null,
templates: [],
};
},
async created() {
this.isLoading = true;
try {
[this.user, this.templates] = await Promise.all([
fetchUser(),
fetchTemplates(),
]);
} finally {
this.isLoading = false;
}
},
};
Schritt 3: Bedingtes Rendern von Skeletons
<template>
<div class="user-profile">
<v-skeleton-loader
v-if="isLoading"
type="
table-heading,
image,
list-item-two-line,
list-item-two-line,
list-item-two-line"
></v-skeleton-loader>
<v-card v-else>
<h2>{{ user.name }}</h2>
<v-card v-for="tpl in templates" :key="tpl.id">
<v-card-title>{{ tpl.name }}</v-card-title>
<v-card-text>{{ tpl.description }}</v-card-text>
</v-card>
</div>
</div>
</template>
Fortgeschrittene Tipps für das Design von Loadern
- Inhaltstruktur anpassen: Gestalten Sie Skeletons so, dass sie Ihr tatsächliches Layout widerspiegeln (z. B. Platzhalter für Bilder, Textzeilen).
- Priorisieren Sie Inhalte über der Falte: Zeigen Sie Loader für sichtbare Inhalte zuerst an, während Hintergrunddaten geladen werden.
- Kombinieren Sie mit Caching: Wenn zwischengespeicherte Daten vorhanden sind, überspringen Sie Skeletons und zeigen Sie die Daten sofort an.
Warum das wichtig ist
- Benutzererfahrung: 74 % der Benutzer bemerken Ladezeiten (PWA Stats).
- Wahrgenommene Leistung: Loader lassen Wartezeiten 15-30 % kürzer erscheinen (NNGroup Research).
- Markenvertrauen: Polierte Übergänge signalisieren Professionalität.
Alles zusammenfassen
Durch die Kombination von parallelen Anfragen, intelligentem Caching und Skeleton-Loadern konnten wir erhebliche Verbesserungen erzielen:
- Schnellere anfängliche Ladezeiten: Parallele Anfragen verkürzen die Datenladezeiten erheblich.
- Reibungslosere Navigation: Wiederverwendete Antworten reduzierten redundante Netzwerkaufrufe.
- Verbesserte Benutzerbindung: Skeleton-Loader verbesserten visuelles Feedback und wahrgenommene Geschwindigkeit.
Die Optimierung der API-Nutzung geht nicht nur um rohe Leistung—sie verbessert auch die Benutzererfahrung. Wir werden weiterhin unser Frontend verfeinern, um Semaphore UI mit jedem Update schneller und benutzerfreundlicher zu gestalten.