feat: implement automatic image optimization with Astro Assets
- Configure content collections to use image() helper for type-safe image references - Replace all <img> tags with <Image> component from astro:assets - Migrate images from /public to /src/assets for automatic optimization - Update blog posts to use relative paths in frontmatter (../../assets/photos/) - Remove unused images and duplicates from /public folder - Update Footer component to use optimized SVG icons - Clean up manifest.json to use favicon.ico instead of deleted photos Performance improvements: - remote.jpg: 1.8MB → 128KB (93% reduction) - me.png: 71KB → 12KB (83% reduction) - Automatic WebP conversion - Tree-shaking: only used images are optimized /public folder reduced from 2.3MB to 32KB (only essential files) Build output: 2.2MB with fully optimized images ready for S3 deployment
This commit is contained in:
parent
da03ed9e6f
commit
289dc9ef00
47 changed files with 632 additions and 419 deletions
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { getCollection } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Navbar from "../../components/Navbar.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
|
|
@ -18,13 +19,15 @@ export async function getStaticPaths() {
|
|||
|
||||
const { entry }: { entry: BlogPost } = Astro.props;
|
||||
const { Content } = await entry.render();
|
||||
|
||||
// Extract image src for meta tags (Open Graph expects a URL string)
|
||||
const heroImageSrc = entry.data.heroImage?.src || "/photos/me.png";
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${entry.data.title} | Lorenzo Iovino`}
|
||||
description={entry.data.description}
|
||||
canonicalUrl={`https://www.lorenzoiovino.com/blog/${entry.slug}`}
|
||||
image={entry.data.heroImage || "/photos/me.png"}
|
||||
image={heroImageSrc}
|
||||
type="article"
|
||||
publishedTime={entry.data.pubDate}
|
||||
modifiedTime={entry.data.updatedDate}
|
||||
|
|
@ -69,10 +72,14 @@ const { Content } = await entry.render();
|
|||
entry.data.heroImage && (
|
||||
<div class="mb-8 md:mb-12 -mx-4 sm:mx-0">
|
||||
<div class="relative h-64 sm:h-80 md:h-96 overflow-hidden sm:rounded-2xl shadow-xl">
|
||||
<img
|
||||
<Image
|
||||
src={entry.data.heroImage}
|
||||
alt={entry.data.title}
|
||||
class="w-full h-full object-cover"
|
||||
width={1200}
|
||||
height={630}
|
||||
quality={80}
|
||||
format="webp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -91,6 +98,8 @@ const { Content } = await entry.render();
|
|||
src="/photos/me.png"
|
||||
alt="Lorenzo Iovino"
|
||||
class="w-20 h-20 rounded-full object-cover"
|
||||
width="80"
|
||||
height="80"
|
||||
/>
|
||||
<div>
|
||||
<h3 class="text-lg md:text-xl font-bold text-gray-900 mb-2">Lorenzo Iovino</h3>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue