Fix: Add base64 placeholder for hero video and squash all massive photo assets down to max 1920px
This commit is contained in:
44
scripts/generate-placeholders.ts
Normal file
44
scripts/generate-placeholders.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import sharp from 'sharp';
|
||||
|
||||
const PUBLIC_DIR = path.join(process.cwd(), 'public');
|
||||
const IMAGES_TO_PROCESS = [
|
||||
'/assets/photos/DJI_0048.JPG',
|
||||
'/assets/videos/web/hero-bahnkreuzung-poster.jpg',
|
||||
'/assets/videos/web/hero-bohrung-poster.jpg',
|
||||
'/assets/videos/web/hero-kabelpflug-poster.jpg',
|
||||
'/assets/videos/web/hero-messe-poster.jpg',
|
||||
];
|
||||
|
||||
async function generatePlaceholders() {
|
||||
const placeholders: Record<string, string> = {};
|
||||
|
||||
for (const imagePath of IMAGES_TO_PROCESS) {
|
||||
const fullPath = path.join(PUBLIC_DIR, imagePath);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.warn(`File not found: ${fullPath}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = await sharp(fullPath)
|
||||
.resize(10, 10, { fit: 'inside' })
|
||||
.blur(2) // Adding slight blur
|
||||
.webp({ quality: 20 })
|
||||
.toBuffer();
|
||||
|
||||
const base64 = `data:image/webp;base64,${buffer.toString('base64')}`;
|
||||
placeholders[imagePath] = base64;
|
||||
console.log(`Generated placeholder for ${imagePath}`);
|
||||
} catch (e) {
|
||||
console.error(`Failed to generate placeholder for ${imagePath}`, e);
|
||||
}
|
||||
}
|
||||
|
||||
const outputPath = path.join(process.cwd(), 'lib', 'placeholders.json');
|
||||
fs.writeFileSync(outputPath, JSON.stringify(placeholders, null, 2));
|
||||
console.log(`Saved placeholders to ${outputPath}`);
|
||||
}
|
||||
|
||||
generatePlaceholders();
|
||||
41
scripts/optimize-images.ts
Normal file
41
scripts/optimize-images.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import sharp from 'sharp';
|
||||
|
||||
const PHOTOS_DIR = path.join(process.cwd(), 'public', 'assets', 'photos');
|
||||
|
||||
async function optimizeImages() {
|
||||
const files = fs.readdirSync(PHOTOS_DIR);
|
||||
let optimized = 0;
|
||||
|
||||
for (const file of files) {
|
||||
if (!file.match(/\.(jpg|jpeg|png)$/i)) continue;
|
||||
|
||||
const filePath = path.join(PHOTOS_DIR, file);
|
||||
const metadata = await sharp(filePath).metadata();
|
||||
|
||||
// If image is larger than 1920px wide, or is a massive file
|
||||
if ((metadata.width && metadata.width > 1920) || fs.statSync(filePath).size > 1024 * 1024) {
|
||||
console.log(`Optimizing ${file} (Width: ${metadata.width}, Size: ${Math.round(fs.statSync(filePath).size / 1024)}KB)`);
|
||||
|
||||
const tmpPath = `${filePath}.tmp`;
|
||||
try {
|
||||
await sharp(filePath)
|
||||
.resize({ width: 1920, withoutEnlargement: true })
|
||||
.jpeg({ quality: 80, progressive: true })
|
||||
.toFile(tmpPath);
|
||||
|
||||
fs.renameSync(tmpPath, filePath);
|
||||
console.log(`✅ Optimized ${file} (New Size: ${Math.round(fs.statSync(filePath).size / 1024)}KB)`);
|
||||
optimized++;
|
||||
} catch (err) {
|
||||
console.error(`Failed to optimize ${file}`, err);
|
||||
if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Finished optimizing ${optimized} images.`);
|
||||
}
|
||||
|
||||
optimizeImages();
|
||||
Reference in New Issue
Block a user