feat(front-end): faster load
All checks were successful
Build and Deploy / test-backend (push) Successful in 31s
Build and Deploy / test-frontend (push) Successful in 1m5s
Build and Deploy / build-and-push (push) Successful in 29s
Build and Deploy / deploy (push) Successful in 19s

This commit is contained in:
2026-03-14 19:28:30 +01:00
parent 996e95f93c
commit df63937406
5 changed files with 238 additions and 45 deletions

View File

@@ -1,5 +1,6 @@
import { CommonModule, isPlatformBrowser } from '@angular/common';
import {
afterNextRender,
Component,
DestroyRef,
Injector,
@@ -193,16 +194,9 @@ export class ProductDetailComponent {
);
constructor() {
if (!this.shopService.cartLoaded()) {
this.shopService
.loadCart()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
error: () => {
this.shopService.cart.set(null);
},
});
}
afterNextRender(() => {
this.scheduleCartWarmup();
});
combineLatest([
toObservable(this.productSlug, { injector: this.injector }),
@@ -279,7 +273,46 @@ export class ProductDetailComponent {
this.shopService.resolveMediaUrl(image.hero) ??
this.shopService.resolveMediaUrl(image.card) ??
this.shopService.resolveMediaUrl(image.thumb)
);
);
}
private scheduleCartWarmup(): void {
if (typeof window === 'undefined') {
this.loadCartIfNeeded();
return;
}
const warmup = () => this.loadCartIfNeeded();
const idleCallback = (
window as Window & {
requestIdleCallback?: (
callback: IdleRequestCallback,
options?: IdleRequestOptions,
) => number;
}
).requestIdleCallback;
if (typeof idleCallback === 'function') {
idleCallback(() => warmup(), { timeout: 1500 });
return;
}
window.setTimeout(warmup, 300);
}
private loadCartIfNeeded(): void {
if (this.shopService.cartLoaded() || this.shopService.cartLoading()) {
return;
}
this.shopService
.loadCart()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
error: () => {
this.shopService.cart.set(null);
},
});
}
selectImage(mediaAssetId: string): void {

View File

@@ -1,5 +1,6 @@
import { CommonModule } from '@angular/common';
import {
afterNextRender,
Component,
DestroyRef,
Injector,
@@ -89,16 +90,9 @@ export class ShopPageComponent {
readonly cartHasItems = computed(() => this.cartItems().length > 0);
constructor() {
if (!this.shopService.cartLoaded()) {
this.shopService
.loadCart()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
error: () => {
this.shopService.cart.set(null);
},
});
}
afterNextRender(() => {
this.scheduleCartWarmup();
});
combineLatest([
toObservable(this.categorySlug, { injector: this.injector }),
@@ -150,6 +144,45 @@ export class ShopPageComponent {
});
}
private scheduleCartWarmup(): void {
if (typeof window === 'undefined') {
this.loadCartIfNeeded();
return;
}
const warmup = () => this.loadCartIfNeeded();
const idleCallback = (
window as Window & {
requestIdleCallback?: (
callback: IdleRequestCallback,
options?: IdleRequestOptions,
) => number;
}
).requestIdleCallback;
if (typeof idleCallback === 'function') {
idleCallback(() => warmup(), { timeout: 1500 });
return;
}
window.setTimeout(warmup, 300);
}
private loadCartIfNeeded(): void {
if (this.shopService.cartLoaded() || this.shopService.cartLoading()) {
return;
}
this.shopService
.loadCart()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
error: () => {
this.shopService.cart.set(null);
},
});
}
productCartQuantity(productId: string): number {
return this.shopService.quantityForProduct(productId);
}