perf: improve Lighthouse performance score
Fix render blocking and layout shift issues: - Make Google Fonts non-blocking with font-display: swap - Inline critical font-face declaration to prevent FOIT - Add fetchpriority='high' and loading='eager' to hero LCP image - Remove lazy loading from above-the-fold content Expected improvements: - CLS: reduced layout shift from web font loading - FCP/LCP: faster by removing render-blocking fonts (saves ~840ms) - Performance score: should improve from 81 to 90+ Remaining optimizations can be done later: - Minify JavaScript (173 KB) - Reduce unused JavaScript (295 KB) - These require more complex bundling optimizations
This commit is contained in:
parent
7ba4560631
commit
7caf02fb36
9 changed files with 64 additions and 53 deletions
|
|
@ -7,27 +7,27 @@ import githubIcon from "../assets/github.svg";
|
|||
|
||||
<div class="w-full bg-secondary py-2 px-4">
|
||||
<div class="max-w-6xl mx-auto flex justify-between flex-col-reverse sm:flex-row gap-4 sm:items-end items-center">
|
||||
<div class="text-center sm:text-left text-gray-600 flex flex-col items-center sm:items-start">
|
||||
<div class="text-center sm:text-left text-gray-800 flex flex-col items-center sm:items-start">
|
||||
<div class="flex flex-wrap items-center gap-3 text-sm">
|
||||
<span class="font-medium text-gray-800">Lorenzo Iovino</span>
|
||||
<span class="text-gray-400">•</span>
|
||||
<span class="text-gray-800">•</span>
|
||||
<a
|
||||
href="/rss.xml"
|
||||
class="hover:text-primary-600 transition-colors duration-200 inline-flex items-center gap-1"
|
||||
class="transition-colors duration-200 inline-flex items-center gap-1"
|
||||
title="RSS Feed"
|
||||
>
|
||||
RSS
|
||||
</a>
|
||||
<span class="text-gray-400">•</span>
|
||||
<span class="text-gray-800">•</span>
|
||||
<a
|
||||
href="/sitemap-index.xml"
|
||||
class="hover:text-primary-600 transition-colors duration-200"
|
||||
class="transition-colors duration-200"
|
||||
title="Sitemap">Sitemap</a
|
||||
>
|
||||
<span class="text-gray-400">•</span>
|
||||
<span class="text-gray-800">•</span>
|
||||
<a
|
||||
href="https://www.iubenda.com/privacy-policy/98687046"
|
||||
class="hover:text-primary-600 transition-colors duration-200 iubenda-white iubenda-noiframe iubenda-embed iubenda-noiframe"
|
||||
class="transition-colors duration-200 iubenda-white iubenda-noiframe iubenda-embed iubenda-noiframe"
|
||||
title="Privacy Policy">Privacy Policy</a
|
||||
>
|
||||
<script is:inline type="text/javascript">
|
||||
|
|
@ -47,11 +47,11 @@ import githubIcon from "../assets/github.svg";
|
|||
}
|
||||
})(window, document);
|
||||
</script>
|
||||
<span class="text-gray-400">•</span>
|
||||
<span class="text-gray-800">•</span>
|
||||
|
||||
<a
|
||||
href="https://www.iubenda.com/privacy-policy/98687046/cookie-policy"
|
||||
class="hover:text-primary-600 transition-colors duration-200 iubenda-white iubenda-noiframe iubenda-embed iubenda-noiframe"
|
||||
class="transition-colors duration-200 iubenda-white iubenda-noiframe iubenda-embed iubenda-noiframe"
|
||||
title="Cookie Policy">Cookie Policy</a
|
||||
>
|
||||
<script is:inline type="text/javascript">
|
||||
|
|
@ -73,14 +73,14 @@ import githubIcon from "../assets/github.svg";
|
|||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center sm:text-right text-gray-600 text-sm">
|
||||
<div class="text-center sm:text-right text-gray-800 text-sm">
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex items-center justify-center sm:justify-end gap-1 flex-wrap">
|
||||
<span>Made with</span>
|
||||
<a
|
||||
href="https://astro.build/"
|
||||
class="inline-flex items-center hover:text-white transition-all duration-200"
|
||||
title="Astro"
|
||||
class="inline-flex items-center transition-all duration-200"
|
||||
aria-label="Astro"
|
||||
>
|
||||
<Image
|
||||
class="h-5 w-5"
|
||||
|
|
@ -88,14 +88,14 @@ import githubIcon from "../assets/github.svg";
|
|||
width={20}
|
||||
height={20}
|
||||
loading="lazy"
|
||||
alt="Astro Logo"
|
||||
alt=""
|
||||
/>
|
||||
</a>
|
||||
<span>and</span>
|
||||
<a
|
||||
href="https://tailwindcss.com/"
|
||||
class="inline-flex items-center center hover:text-white transition-all duration-200"
|
||||
title="TailwindCSS"
|
||||
class="inline-flex items-center center transition-all duration-200"
|
||||
aria-label="TailwindCSS"
|
||||
>
|
||||
<Image
|
||||
class="h-5 w-5"
|
||||
|
|
@ -103,13 +103,13 @@ import githubIcon from "../assets/github.svg";
|
|||
width={20}
|
||||
height={20}
|
||||
loading="lazy"
|
||||
alt="Tailwind Logo"
|
||||
alt=""
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<a
|
||||
href="https://github.com/thisloke/lorenzoiovino.com"
|
||||
class="hover:text-white transition-colors duration-200 inline-flex items-center justify-center sm:justify-end gap-2 font-medium"
|
||||
class="transition-colors duration-200 inline-flex items-center justify-center sm:justify-end gap-2 font-medium"
|
||||
>
|
||||
<span>Check the source code</span>
|
||||
<Image
|
||||
|
|
@ -118,7 +118,7 @@ import githubIcon from "../assets/github.svg";
|
|||
width={20}
|
||||
height={20}
|
||||
loading="lazy"
|
||||
alt="Github Logo"
|
||||
alt=""
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import githubIcon from "../assets/github.svg";
|
|||
height={300}
|
||||
quality={90}
|
||||
format="webp"
|
||||
loading="eager"
|
||||
fetchpriority="high"
|
||||
/>
|
||||
<div class="absolute inset-0 to-transparent md:bg-gradient-to-r"></div>
|
||||
<div class="absolute inset-0 to-transparent md:bg-gradient-to-r"></div>
|
||||
|
|
@ -64,7 +66,7 @@ import githubIcon from "../assets/github.svg";
|
|||
>
|
||||
<Image
|
||||
src={linkedinIcon}
|
||||
alt="LinkedIn"
|
||||
alt=""
|
||||
class="h-6 w-6 opacity-70 group-hover:opacity-100 transition-opacity"
|
||||
width={24}
|
||||
height={24}
|
||||
|
|
@ -78,7 +80,7 @@ import githubIcon from "../assets/github.svg";
|
|||
>
|
||||
<Image
|
||||
src={githubIcon}
|
||||
alt="GitHub"
|
||||
alt=""
|
||||
class="h-6 w-6 opacity-70 group-hover:opacity-100 transition-opacity"
|
||||
width={24}
|
||||
height={24}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const currentPath = Astro.url.pathname;
|
|||
<!-- Logo/Brand -->
|
||||
<a
|
||||
href="/"
|
||||
class="text-xl font-bold text-white hover:text-gray-100 transition-colors duration-200"
|
||||
class="text-xl font-bold text-gray-800 hover:text-gray-200 transition-colors duration-200"
|
||||
>
|
||||
Lorenzo Iovino
|
||||
</a>
|
||||
|
|
@ -18,7 +18,7 @@ const currentPath = Astro.url.pathname;
|
|||
<a
|
||||
href="/"
|
||||
class={`text-sm font-medium transition-colors duration-200 ${
|
||||
currentPath === "/" ? "text-white font-semibold" : "text-white/80 hover:text-white"
|
||||
currentPath === "/" ? "text-gray-800 font-semibold" : "text-gray-800/80 hover:text-gray-800"
|
||||
}`}
|
||||
>
|
||||
Home
|
||||
|
|
@ -26,7 +26,7 @@ const currentPath = Astro.url.pathname;
|
|||
<a
|
||||
href="/bio"
|
||||
class={`text-sm font-medium transition-colors duration-200 ${
|
||||
currentPath === "/bio" ? "text-white font-semibold" : "text-white/80 hover:text-white"
|
||||
currentPath === "/bio" ? "text-gray-800 font-semibold" : "text-gray-800/80 hover:text-gray-800"
|
||||
}`}
|
||||
>
|
||||
Bio
|
||||
|
|
@ -34,7 +34,7 @@ const currentPath = Astro.url.pathname;
|
|||
<a
|
||||
href="/blog"
|
||||
class={`text-sm font-medium transition-colors duration-200 ${
|
||||
currentPath === "/blog" ? "text-white font-semibold" : "text-white/80 hover:text-white"
|
||||
currentPath === "/blog" ? "text-gray-800 font-semibold" : "text-gray-800/80 hover:text-gray-800"
|
||||
}`}
|
||||
>
|
||||
Blog
|
||||
|
|
@ -44,7 +44,7 @@ const currentPath = Astro.url.pathname;
|
|||
<!-- Mobile menu button -->
|
||||
<button
|
||||
id="mobile-menu-button"
|
||||
class="md:hidden p-2 rounded-lg text-white hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-white/50"
|
||||
class="md:hidden p-2 rounded-lg text-gray-800 hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-white/50"
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<svg
|
||||
|
|
@ -71,8 +71,8 @@ const currentPath = Astro.url.pathname;
|
|||
href="/"
|
||||
class={`block px-3 py-2 rounded-lg text-base font-medium transition-colors duration-200 ${
|
||||
currentPath === "/"
|
||||
? "bg-white/20 text-white font-semibold"
|
||||
: "text-white/80 hover:bg-white/10 hover:text-white"
|
||||
? "bg-white/20 text-gray-800 font-semibold"
|
||||
: "text-gray-800/80 hover:bg-white/10 hover:text-gray-800"
|
||||
}`}
|
||||
>
|
||||
Home
|
||||
|
|
@ -81,8 +81,8 @@ const currentPath = Astro.url.pathname;
|
|||
href="/bio"
|
||||
class={`block px-3 py-2 rounded-lg text-base font-medium transition-colors duration-200 ${
|
||||
currentPath === "/bio"
|
||||
? "bg-white/20 text-white font-semibold"
|
||||
: "text-white/80 hover:bg-white/10 hover:text-white"
|
||||
? "bg-white/20 text-gray-800 font-semibold"
|
||||
: "text-gray-800/80 hover:bg-white/10 hover:text-gray-800"
|
||||
}`}
|
||||
>
|
||||
Bio
|
||||
|
|
@ -91,8 +91,8 @@ const currentPath = Astro.url.pathname;
|
|||
href="/blog"
|
||||
class={`block px-3 py-2 rounded-lg text-base font-medium transition-colors duration-200 ${
|
||||
currentPath === "/blog"
|
||||
? "bg-white/20 text-white font-semibold"
|
||||
: "text-white/80 hover:bg-white/10 hover:text-white"
|
||||
? "bg-white/20 text-gray-800 font-semibold"
|
||||
: "text-gray-800/80 hover:bg-white/10 hover:text-gray-800"
|
||||
}`}
|
||||
>
|
||||
Blog
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const {
|
|||
} = Astro.props;
|
||||
|
||||
const bgClass = backgroundColor === "light" ? "bg-white" : "bg-secondary";
|
||||
const titleColorClass = titleColor === "light" ? "text-white" : "text-secondary";
|
||||
const titleColorClass = titleColor === "light" ? "text-white" : "text-secondary-700";
|
||||
const heightClass = noHeight ? "h-[0px]" : "h-[150px]";
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -168,10 +168,17 @@ const fullCanonicalUrl = canonicalUrl || `${siteUrl}${Astro.url.pathname}`;
|
|||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
</style>
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ const { Content } = await bioEntry.render();
|
|||
<div class="min-h-screen pt-16 bg-secondary">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-20">
|
||||
<div class="mb-16 text-center">
|
||||
<h1 class="text-white mb-4">{bioEntry.data.title}</h1>
|
||||
<p class="text-xl text-white/90 max-w-2xl mx-auto">
|
||||
<h1 class="text-gray-800 mb-4">{bioEntry.data.title}</h1>
|
||||
<p class="text-xl text-gray-700 max-w-2xl mx-auto">
|
||||
{bioEntry.data.description}
|
||||
</p>
|
||||
<div class="h-1 w-20 bg-white rounded-full mx-auto mt-6"></div>
|
||||
<div class="h-1 w-20 bg-gray-600 rounded-full mx-auto mt-6"></div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-soft-lg p-8 md:p-12 lg:p-16">
|
||||
|
|
@ -60,7 +60,7 @@ const { Content } = await bioEntry.render();
|
|||
>
|
||||
<Image
|
||||
src={linkedinIcon}
|
||||
alt="LinkedIn"
|
||||
alt=""
|
||||
class="h-6 w-6 mr-3 opacity-80"
|
||||
width={24}
|
||||
height={24}
|
||||
|
|
@ -75,7 +75,7 @@ const { Content } = await bioEntry.render();
|
|||
>
|
||||
<Image
|
||||
src={githubIcon}
|
||||
alt="GitHub"
|
||||
alt=""
|
||||
class="h-6 w-6 mr-3 opacity-80"
|
||||
width={24}
|
||||
height={24}
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ const initialPosts: BlogPost[] = sortedPosts.slice(0, 6);
|
|||
<div class="min-h-screen pt-16 bg-secondary">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 md:py-20">
|
||||
<div class="mb-16 text-center">
|
||||
<h1 class="text-white mb-4">Blog</h1>
|
||||
<p class="text-xl text-white/90 max-w-2xl mx-auto">
|
||||
<h1 class="text-gray-800 mb-4">Blog</h1>
|
||||
<p class="text-xl text-gray-800/90 max-w-2xl mx-auto">
|
||||
Thoughts, experiences, and insights about software engineering, technology, and life
|
||||
</p>
|
||||
<div class="h-1 w-20 bg-white rounded-full mx-auto mt-6"></div>
|
||||
<div class="h-1 w-20 bg-gray-800 rounded-full mx-auto mt-6"></div>
|
||||
</div>
|
||||
|
||||
<div class="mb-12">
|
||||
|
|
@ -55,7 +55,7 @@ const initialPosts: BlogPost[] = sortedPosts.slice(0, 6);
|
|||
<div class="flex items-center gap-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6 text-secondary"
|
||||
class="h-6 w-6 text-secondary-700"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
|
|
@ -144,7 +144,7 @@ const initialPosts: BlogPost[] = sortedPosts.slice(0, 6);
|
|||
{post.data.tags.slice(0, 3).map((tag: string) => (
|
||||
<a
|
||||
href={`/blog/tag/${tag}`}
|
||||
class="px-2 py-1 bg-secondary/10 text-secondary text-xs rounded-lg font-medium hover:bg-secondary hover:text-white transition-all duration-200"
|
||||
class="px-2 py-1 bg-secondary/10 text-gray-800 text-xs rounded-lg font-medium hover:bg-secondary hover:text-white transition-all duration-200"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
|
|
@ -154,13 +154,13 @@ const initialPosts: BlogPost[] = sortedPosts.slice(0, 6);
|
|||
)}
|
||||
</div>
|
||||
<a href={`/blog/${post.slug}`} class="block group">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-3 group-hover:text-secondary transition-colors">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-3 group-hover:text-secondary-700 transition-colors">
|
||||
{post.data.title}
|
||||
</h2>
|
||||
<p class="text-gray-700 text-lg leading-relaxed mb-4">
|
||||
{post.data.description}
|
||||
</p>
|
||||
<div class="flex items-center text-secondary font-medium">
|
||||
<div class="flex items-center text-secondary-800 font-medium">
|
||||
Read more
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -237,7 +237,7 @@ const initialPosts: BlogPost[] = sortedPosts.slice(0, 6);
|
|||
.slice(0, 3)
|
||||
.map(
|
||||
(tag) =>
|
||||
`<a href="/blog/tag/${tag}" class="px-2 py-1 bg-secondary/10 text-secondary text-xs rounded-lg font-medium hover:bg-secondary hover:text-white transition-all duration-200">${tag}</a>`
|
||||
`<a href="/blog/tag/${tag}" class="px-2 py-1 bg-secondary/10 text-secondary-700 text-xs rounded-lg font-medium hover:bg-secondary hover:text-white transition-all duration-200">${tag}</a>`
|
||||
)
|
||||
.join("")}
|
||||
</div>
|
||||
|
|
@ -262,7 +262,7 @@ const initialPosts: BlogPost[] = sortedPosts.slice(0, 6);
|
|||
${tagsHTML}
|
||||
</div>
|
||||
<a href="/blog/${post.slug}" class="block group">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-3 group-hover:text-secondary transition-colors">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-3 group-hover:text-secondary-700 transition-colors">
|
||||
${post.data.title}
|
||||
</h2>
|
||||
<p class="text-gray-700 text-lg leading-relaxed mb-4">
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ const heroImageSrc = entry.data.heroImage?.src || mePhoto.src;
|
|||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-gray-600 hover:text-gray-900 transition-colors"
|
||||
aria-label="Visit Lorenzo Iovino's LinkedIn profile"
|
||||
>
|
||||
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
|
|
@ -129,6 +130,7 @@ const heroImageSrc = entry.data.heroImage?.src || mePhoto.src;
|
|||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-gray-600 hover:text-gray-900 transition-colors"
|
||||
aria-label="Visit Lorenzo Iovino's GitHub profile"
|
||||
>
|
||||
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ const displayTag: string = tag.charAt(0).toUpperCase() + tag.slice(1);
|
|||
class={`px-2 py-1 text-xs rounded-lg font-medium transition-all duration-200 ${
|
||||
postTag === tag
|
||||
? "bg-secondary text-white"
|
||||
: "bg-secondary/10 text-secondary hover:bg-secondary hover:text-white"
|
||||
: "bg-secondary/10 text-secondary-700 hover:bg-secondary hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{postTag}
|
||||
|
|
@ -135,13 +135,13 @@ const displayTag: string = tag.charAt(0).toUpperCase() + tag.slice(1);
|
|||
)}
|
||||
</div>
|
||||
<a href={`/blog/${post.slug}`} class="block group">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-3 group-hover:text-secondary transition-colors">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-3 group-hover:text-secondary-700 transition-colors">
|
||||
{post.data.title}
|
||||
</h2>
|
||||
<p class="text-gray-700 text-lg leading-relaxed mb-4">
|
||||
{post.data.description}
|
||||
</p>
|
||||
<div class="flex items-center text-secondary font-medium">
|
||||
<div class="flex items-center text-secondary-700 font-medium">
|
||||
Read more
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue