perf(images): generate WebP variants and reference optimized images
This commit is contained in:
+9
-2
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import Me from './assets/Me.jpeg';
|
||||
|
||||
export const Home = () => {
|
||||
return (
|
||||
@@ -25,7 +24,15 @@ export const Home = () => {
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<img src={Me} alt="Portrait of Gregory Campbell" className="homeimage" loading="lazy" decoding="async" />
|
||||
<img
|
||||
src="/images/Me-640.webp"
|
||||
srcSet="/images/Me-320.webp 320w, /images/Me-640.webp 640w, /images/Me-1024.webp 1024w"
|
||||
sizes="(max-width: 600px) 100vw, 640px"
|
||||
alt="Portrait of Gregory Campbell"
|
||||
className="homeimage"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
|
||||
+8
-16
@@ -1,70 +1,62 @@
|
||||
import React from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import ProjectCard from './components/ProjectCard';
|
||||
import ShowingOff from './assets/ShowingOff.jpg';
|
||||
import StateMachine from './assets/StateMachine.png';
|
||||
import Skin2 from './assets/skin2.png';
|
||||
import EulerExample from './assets/EulerExample.png';
|
||||
import Hangman from './assets/Hangman.png';
|
||||
import KngihtsTour from './assets/KnightsTour.png';
|
||||
import TextAnalyzer from './assets/TextAnalyzer.png';
|
||||
import AlgorithmComparison from './assets/AlgorithmComparison.png';
|
||||
|
||||
const projects = [
|
||||
{
|
||||
title: 'Python State Machine',
|
||||
link: 'https://github.com/gjcampbell777/python-state-machine',
|
||||
description: 'A Python state machine used to emulate a locked/unlocked device.',
|
||||
img: StateMachine,
|
||||
imgName: 'StateMachine',
|
||||
imgAlt: 'Python state machine demo'
|
||||
},
|
||||
{
|
||||
title: 'Python Skin Detection Algorithms',
|
||||
link: 'https://github.com/gjcampbell777/python-photo-skin-detection',
|
||||
description: 'Replicated multiple skin detection algorithms in Python and modernized them for Python 3.',
|
||||
img: Skin2,
|
||||
imgName: 'skin2',
|
||||
imgAlt: 'Skin detection before/after',
|
||||
},
|
||||
{
|
||||
title: 'Euler Checking Algorithm',
|
||||
link: 'https://github.com/gjcampbell777/euler-checking-algorithm',
|
||||
description: 'C program to check if graphs are Eulerian.',
|
||||
img: EulerExample,
|
||||
imgName: 'EulerExample',
|
||||
imgAlt: 'Euler example'
|
||||
},
|
||||
{
|
||||
title: 'Fortran Hangman',
|
||||
link: 'https://github.com/gjcampbell777/fortran-hangman',
|
||||
description: 'Updated a Fortran 77 hangman game to Fortran 95 and improved the code.',
|
||||
img: Hangman,
|
||||
imgName: 'Hangman',
|
||||
imgAlt: 'Hangman game'
|
||||
},
|
||||
{
|
||||
title: "Ada Knights Tour",
|
||||
link: 'https://github.com/gjcampbell777/ada-knights-tour',
|
||||
description: "Solves the knight's tour problem in Ada.",
|
||||
img: KngihtsTour,
|
||||
imgName: 'KnightsTour',
|
||||
imgAlt: 'Knights tour output'
|
||||
},
|
||||
{
|
||||
title: 'COBOL Text Analyzer',
|
||||
link: 'https://github.com/gjcampbell777/cobol-text-analyzer',
|
||||
description: 'Modernized COBOL text analyzer to report text statistics.',
|
||||
img: TextAnalyzer,
|
||||
imgName: 'TextAnalyzer',
|
||||
imgAlt: 'Text analyzer output'
|
||||
},
|
||||
{
|
||||
title: 'Legacy Algorithm Comparison',
|
||||
link: 'https://github.com/gjcampbell777/legacy-algorithm-comparison',
|
||||
description: 'Compare KMP implementations across C, Fortran, and Ada.',
|
||||
img: AlgorithmComparison,
|
||||
imgName: 'AlgorithmComparison',
|
||||
imgAlt: 'Algorithm comparison charts'
|
||||
},
|
||||
{
|
||||
title: 'My Many Games',
|
||||
link: 'https://gregorysoup.itch.io',
|
||||
description: 'A selection of games made with Unity and Godot.',
|
||||
img: ShowingOff,
|
||||
imgName: 'ShowingOff',
|
||||
imgAlt: 'Game showcase'
|
||||
}
|
||||
];
|
||||
|
||||
+8
-2
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import pdf from './assets/Gregory Campbell Resume.pdf';
|
||||
import pic from './assets/Resume.png';
|
||||
|
||||
export const Resume = () => {
|
||||
return (
|
||||
@@ -26,7 +25,14 @@ export const Resume = () => {
|
||||
|
||||
<section>
|
||||
<h2>Written Resume</h2>
|
||||
<img src={pic} alt="Resume preview" loading="lazy" decoding="async" />
|
||||
<img
|
||||
src="/images/Resume-640.webp"
|
||||
srcSet="/images/Resume-320.webp 320w, /images/Resume-640.webp 640w, /images/Resume-1024.webp 1024w"
|
||||
sizes="(max-width: 600px) 100vw, 640px"
|
||||
alt="Resume preview"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
import React from 'react';
|
||||
|
||||
export const ProjectCard = ({ title, description, imgSrc, imgAlt, link, children }) => {
|
||||
export const ProjectCard = ({ title, description, imgSrc, imgName, imgAlt, link, children }) => {
|
||||
const webpSources = imgName
|
||||
? `/images/${imgName}-320.webp 320w, /images/${imgName}-640.webp 640w, /images/${imgName}-1024.webp 1024w`
|
||||
: null;
|
||||
|
||||
const srcFallback = imgName ? `/images/${imgName}-640.webp` : imgSrc;
|
||||
|
||||
return (
|
||||
<article className="project-card">
|
||||
<h3>
|
||||
{link ? (
|
||||
<a href={link} target="_blank" rel="noreferrer noopener">{title}</a>
|
||||
) : (
|
||||
title
|
||||
)}
|
||||
</h3>
|
||||
<h3>{link ? <a href={link} target="_blank" rel="noreferrer noopener">{title}</a> : title}</h3>
|
||||
<p>{description}</p>
|
||||
{imgSrc && (
|
||||
<img src={imgSrc} alt={imgAlt || title} loading="lazy" decoding="async" />
|
||||
{srcFallback && (
|
||||
<img
|
||||
src={srcFallback}
|
||||
srcSet={webpSources || undefined}
|
||||
sizes="(max-width: 600px) 100vw, 640px"
|
||||
alt={imgAlt || title}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</article>
|
||||
|
||||
Reference in New Issue
Block a user