This Angular web application started as an educational assignment while attending Boston University CDIA as a student of web development and was developed originally using PHP and MySQL in 2014. It has been upgraded recently from Angular version 20 to Angular version 21, and has been upgraded regularly since its inception in 2021 https://horsecode-e216d.web.app/signup-login
Upgrading to Angular version 21 provides significant benefits centered on performance, developer experience, and modern architecture, particularly through the full implementation of the standalone APIs and signal-based reactivity.
Key benefits of upgrading to Angular 21 include:
- Performance Improvements: New applications use zoneless change detection by default. Build optimizations, such as esbuild/Vite integration, lead to faster application rendering, smaller bundle sizes (up to 40% reduction), and quicker build times.
- Simplified Reactivity with Signals: Signals are fully integrated, providing a more straightforward method to manage state. This reduces the need for complex RxJS patterns for basic UI updates.
- Enhanced Server-Side Rendering (SSR) & SEO: Improvements to SSR and hydration, such as SSR streaming and faster hydration, result in better Core Web Vitals, improved SEO, and a better user experience.
Image preloader service for the hero images:
`
import { Injectable, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { Subject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class PreloadimgService {
private platformId: object = inject(PLATFORM_ID);
preloadImages(imageUrls: string[]): Observable {
if (!isPlatformBrowser(this.platformId)) {
return new Observable((observer) => observer.complete()); // Skip on server
}
const loadedSubject = new Subject<string>();
let loadedCount = 0;
const totalImages = imageUrls.length;
for (const url of imageUrls) {
const img = new Image();
img.onload = () => {
loadedCount++;
loadedSubject.next(url);
if (loadedCount === totalImages) {
loadedSubject.complete();
}
};
img.onerror = () => {
loadedCount++;
loadedSubject.error(`Failed to load image: ${url}`);
if (loadedCount === totalImages) {
loadedSubject.complete();
}
};
img.src = url;
}
return loadedSubject.asObservable();
`
Image preloader implemented in the component, which precedes the component that uses the images:
`
...
imageLocations: string[] = [
'/images/topic_one.jpg',
'/images/topic_two.jpg',
'/images/topic_three.jpg',
];
allImagesLoaded = false;
private preloader: PreloadimgService = inject(PreloadimgService);
...
ngOnInit(): void {
this.preloader.preloadImages(this.imageLocations).subscribe({
complete: () => {
this.allImagesLoaded = true;
},
error: (err) => console.error(err),
});
}
...
`



Top comments (0)