Improve gallery loading speed with image optimization and lazy loading

Implement a thumbnail proxy endpoint and lazy loading for gallery images to significantly reduce page load times and improve user experience.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 517dfa7b-26ac-463d-a6e1-a58c6df97188
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1488855f-6772-48e1-9244-282d1cc91352
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/517dfa7b-26ac-463d-a6e1-a58c6df97188/VgutZ7W
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic
2026-03-01 18:52:46 +00:00
parent 97d09ba27e
commit 39d43cd876
4 changed files with 616 additions and 535 deletions
+43 -1
View File
@@ -6,7 +6,7 @@ import { seedDatabase } from "./seed";
import { generateDailyHoroscopes, getHoroscopesForToday, getOrGenerateHoroscope } from "./horoscope-generator";
import { analyzeAllArticleImages, getCachedFocalPoints } from "./focal-point";
import { optimizeImage } from "./image-optimizer";
import { getAuthUrl, exchangeCodeForTokens, isConnected, fetchGalleryFromDropbox } from "./dropbox";
import { getAuthUrl, exchangeCodeForTokens, isConnected, fetchGalleryFromDropbox, getValidAccessToken } from "./dropbox";
import multer from "multer";
import path from "path";
import fs from "fs";
@@ -233,6 +233,48 @@ export async function registerRoutes(
res.json({ connected: isConnected() });
});
const thumbCache = new Map<string, { data: Buffer; timestamp: number }>();
const THUMB_CACHE_TTL = 30 * 60 * 1000;
app.get("/api/gallery/thumb", async (req, res) => {
const src = req.query.src as string;
if (!src) return res.status(400).send("Missing src");
const cached = thumbCache.get(src);
if (cached && Date.now() - cached.timestamp < THUMB_CACHE_TTL) {
res.set("Content-Type", "image/jpeg");
res.set("Cache-Control", "public, max-age=1800");
return res.send(cached.data);
}
try {
const resp = await fetch(src);
if (!resp.ok) return res.status(502).send("Upstream error");
const arrayBuf = await resp.arrayBuffer();
const fullBuf = Buffer.from(arrayBuf);
const sharp = (await import("sharp")).default;
const thumbBuf = await sharp(fullBuf)
.resize(400, 400, { fit: "cover", position: "attention" })
.jpeg({ quality: 70 })
.toBuffer();
thumbCache.set(src, { data: thumbBuf, timestamp: Date.now() });
if (thumbCache.size > 300) {
const oldest = [...thumbCache.entries()].sort((a, b) => a[1].timestamp - b[1].timestamp);
for (let i = 0; i < 50; i++) thumbCache.delete(oldest[i][0]);
}
res.set("Content-Type", "image/jpeg");
res.set("Cache-Control", "public, max-age=1800");
res.send(thumbBuf);
} catch (err: any) {
res.status(500).send(err.message);
}
});
app.post("/api/dropbox/refresh-gallery", async (_req, res) => {
try {
const images = await fetchGalleryFromDropbox();