Optimize images for faster loading and better performance
Converts existing JPEG images to WebP format, generates thumbnails for article cards and related articles, and implements lazy loading to improve page load times. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 413891e8-d784-4bea-b9f5-91a5a68316b4 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: c002b3c2-2c7e-4068-b5b7-21bd62b51e6c Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/413891e8-d784-4bea-b9f5-91a5a68316b4/kmpcO4B Replit-Helium-Checkpoint-Created: true
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 100 KiB |
@@ -70,7 +70,7 @@ function RelatedArticles({ currentSlug }: { currentSlug: string }) {
|
|||||||
<div className="group cursor-pointer" data-testid={`card-related-${article.id}`}>
|
<div className="group cursor-pointer" data-testid={`card-related-${article.id}`}>
|
||||||
<div className="relative overflow-hidden rounded-md mb-3">
|
<div className="relative overflow-hidden rounded-md mb-3">
|
||||||
<img
|
<img
|
||||||
src={article.coverImage || "/images/article-1.png"}
|
src={article.coverImage ? article.coverImage.replace(".webp", "-thumb.webp") : "/images/article-1.png"}
|
||||||
alt={article.title}
|
alt={article.title}
|
||||||
className="w-full aspect-video object-cover transition-transform duration-500 group-hover:scale-105"
|
className="w-full aspect-video object-cover transition-transform duration-500 group-hover:scale-105"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
|||||||
@@ -121,6 +121,12 @@ function FeaturedSection({ articles }: { articles: Article[] }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function thumbUrl(src: string | null): string {
|
||||||
|
if (!src) return "/images/article-1.png";
|
||||||
|
if (src.endsWith(".webp")) return src.replace(".webp", "-thumb.webp");
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
function ArticleCard({ article }: { article: Article }) {
|
function ArticleCard({ article }: { article: Article }) {
|
||||||
return (
|
return (
|
||||||
<Link href={`/article/${article.slug}`}>
|
<Link href={`/article/${article.slug}`}>
|
||||||
@@ -131,7 +137,7 @@ function ArticleCard({ article }: { article: Article }) {
|
|||||||
<div className="relative rounded-t-md">
|
<div className="relative rounded-t-md">
|
||||||
<div className="overflow-hidden rounded-t-md">
|
<div className="overflow-hidden rounded-t-md">
|
||||||
<img
|
<img
|
||||||
src={article.coverImage || "/images/article-1.png"}
|
src={thumbUrl(article.coverImage)}
|
||||||
alt={article.title}
|
alt={article.title}
|
||||||
className="w-full aspect-[16/10] object-cover transition-transform duration-500 group-hover:scale-105"
|
className="w-full aspect-[16/10] object-cover transition-transform duration-500 group-hover:scale-105"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
|||||||