1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2025-01-03 02:15:00 +01:00

migrate to gatsby-plugin-image

This commit is contained in:
Matthias Kretschmann 2021-03-13 01:03:23 +01:00
parent 8da788e4d2
commit 9493b9d2ef
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 28285 additions and 139 deletions

View File

@ -117,7 +117,7 @@ Site sends usage statistics to my own [Matomo](https://matomo.org) installation.
All project images live under `content/images` and are automatically attached to each project based on the inclusion of the project's `slug` in their filenames. All project images live under `content/images` and are automatically attached to each project based on the inclusion of the project's `slug` in their filenames.
All project images make use of the excellent [gatsby-image](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-image) plugin, working in tandem with [gatsby-plugin-sharp](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-sharp) and [gatsby-transformer-sharp](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-sharp). All project images make use of the excellent [gatsby-plugin-image](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/) plugin, working in tandem with [gatsby-plugin-sharp](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-sharp) and [gatsby-transformer-sharp](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-sharp).
All together, Gatsby automatically generates all required image sizes for delivering responsible, responsive images to visitors, including lazy loading of all images. Also includes the [intersection-observer polyfill](https://github.com/w3c/IntersectionObserver) to make lazy loading work properly in Safari. All together, Gatsby automatically generates all required image sizes for delivering responsible, responsive images to visitors, including lazy loading of all images. Also includes the [intersection-observer polyfill](https://github.com/w3c/IntersectionObserver) to make lazy loading work properly in Safari.

View File

@ -39,6 +39,9 @@ module.exports = {
}, },
'gatsby-transformer-yaml', 'gatsby-transformer-yaml',
'gatsby-transformer-json', 'gatsby-transformer-json',
'gatsby-plugin-image',
'gatsby-plugin-sharp',
'gatsby-transformer-sharp',
'gatsby-plugin-postcss', 'gatsby-plugin-postcss',
{ {
resolve: 'gatsby-plugin-svgr', resolve: 'gatsby-plugin-svgr',
@ -79,8 +82,6 @@ module.exports = {
} }
}, },
'gatsby-plugin-react-helmet', 'gatsby-plugin-react-helmet',
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
'gatsby-plugin-sitemap', 'gatsby-plugin-sitemap',
'gatsby-plugin-offline', 'gatsby-plugin-offline',
'gatsby-plugin-webpack-size' 'gatsby-plugin-webpack-size'

28206
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
"axios": "^0.21.1", "axios": "^0.21.1",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"gatsby": "^3.0.4", "gatsby": "^3.0.4",
"gatsby-image": "^3.0.0", "gatsby-plugin-image": "^1.0.1",
"gatsby-plugin-manifest": "^3.0.0", "gatsby-plugin-manifest": "^3.0.0",
"gatsby-plugin-matomo": "^0.9.0", "gatsby-plugin-matomo": "^0.9.0",
"gatsby-plugin-offline": "^4.0.0", "gatsby-plugin-offline": "^4.0.0",

View File

@ -11,11 +11,11 @@ import { screen } from './Layout.module.css'
import { useMeta } from '../hooks/use-meta' import { useMeta } from '../hooks/use-meta'
// https://github.com/welldone-software/why-did-you-render // https://github.com/welldone-software/why-did-you-render
if (process.env.NODE_ENV !== 'production') { // if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line // // eslint-disable-next-line
const whyDidYouRender = require('@welldone-software/why-did-you-render') // const whyDidYouRender = require('@welldone-software/why-did-you-render')
whyDidYouRender(React, { trackAllPureComponents: true }) // whyDidYouRender(React, { trackAllPureComponents: true })
} // }
Layout.propTypes = { Layout.propTypes = {
children: PropTypes.any.isRequired, children: PropTypes.any.isRequired,
@ -42,7 +42,7 @@ export default function Layout({ children, location }) {
<HostnameCheck allowedHosts={allowedHosts} /> <HostnameCheck allowedHosts={allowedHosts} />
<ThemeSwitch /> <ThemeSwitch />
<PoseGroup animateOnMount={process.env.NODE_ENV !== 'test' && true}> <PoseGroup animateOnMount={process.env.NODE_ENV !== 'test'}>
<RoutesContainer <RoutesContainer
key={location.pathname} key={location.pathname}
delay={timeout} delay={timeout}

View File

@ -1,31 +1,27 @@
import React, { PureComponent } from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import Img from 'gatsby-image' import { GatsbyImage } from 'gatsby-plugin-image'
import { projectImage as styleProjectImage } from './ProjectImage.module.css' import { projectImage as styleProjectImage } from './ProjectImage.module.css'
export default class ProjectImage extends PureComponent { export default function ProjectImage({ image, alt }) {
static propTypes = { return (
fluid: PropTypes.object.isRequired, <GatsbyImage
alt: PropTypes.string className={styleProjectImage}
} backgroundColor="transparent"
image={image}
alt={alt}
/>
)
}
render() { ProjectImage.propTypes = {
return ( image: PropTypes.object.isRequired,
<Img alt: PropTypes.string.isRequired
className={styleProjectImage}
backgroundColor="transparent"
fluid={this.props.fluid}
alt={this.props.alt}
/>
)
}
} }
export const projectImage = graphql` export const projectImage = graphql`
fragment ProjectImageFluid on ImageSharp { fragment ProjectImageFluid on ImageSharp {
fluid(maxWidth: 1440, quality: 85) { gatsbyImageData(layout: CONSTRAINED, width: 1440, quality: 85)
...GatsbyImageSharpFluid_withWebp_noBase64
}
} }
` `

View File

@ -3,11 +3,12 @@ import saveAs from 'file-saver'
import vCard from 'vcf' import vCard from 'vcf'
import { useMeta } from '../../hooks/use-meta' import { useMeta } from '../../hooks/use-meta'
import { useResume } from '../../hooks/use-resume' import { useResume } from '../../hooks/use-resume'
import { getSrc } from 'gatsby-plugin-image'
export default function Vcard() { export default function Vcard() {
const metaYaml = useMeta() const metaYaml = useMeta()
const { basics } = useResume() const { basics } = useResume()
const photoSrc = basics.picture.childImageSharp.fixed.src const photoSrc = getSrc(basics.picture)
const { name, label, email, profiles } = basics const { name, label, email, profiles } = basics
const meta = { const meta = {

View File

@ -14,9 +14,7 @@ const query = graphql`
slug slug
img { img {
childImageSharp { childImageSharp {
fluid(maxWidth: 500, quality: 85) { gatsbyImageData(layout: CONSTRAINED, width: 500, quality: 85)
...GatsbyImageSharpFluid_noBase64
}
} }
} }
} }
@ -28,7 +26,10 @@ const query = graphql`
const Project = ({ node, refCurrentItem }) => ( const Project = ({ node, refCurrentItem }) => (
<div className={item} ref={refCurrentItem}> <div className={item} ref={refCurrentItem}>
<Link className={link} to={node.slug}> <Link className={link} to={node.slug}>
<ProjectImage fluid={node.img.childImageSharp.fluid} alt={node.title} /> <ProjectImage
image={node.img.childImageSharp.gatsbyImageData}
alt={node.title}
/>
<h1 className={title}>{node.title}</h1> <h1 className={title}>{node.title}</h1>
</Link> </Link>
</div> </div>

View File

@ -25,7 +25,7 @@ ThemeToggle.propTypes = {
dark: PropTypes.bool.isRequired dark: PropTypes.bool.isRequired
} }
const ThemeToggleInput = memo(({ dark, toggleDark }) => ( const ThemeToggleInput = ({ dark, toggleDark }) => (
<input <input
onChange={() => toggleDark()} onChange={() => toggleDark()}
type="checkbox" type="checkbox"
@ -34,7 +34,7 @@ const ThemeToggleInput = memo(({ dark, toggleDark }) => (
aria-describedby="toggle" aria-describedby="toggle"
checked={dark} checked={dark}
/> />
)) )
ThemeToggleInput.displayName = 'ThemeToggleInput' ThemeToggleInput.displayName = 'ThemeToggleInput'
@ -59,7 +59,7 @@ HeadItems.propTypes = {
themeColor: PropTypes.string.isRequired themeColor: PropTypes.string.isRequired
} }
function ThemeSwitch() { export default function ThemeSwitch() {
const { value, toggle } = useDarkMode(false, { const { value, toggle } = useDarkMode(false, {
classNameDark: 'dark', classNameDark: 'dark',
classNameLight: 'light' classNameLight: 'light'
@ -85,5 +85,3 @@ function ThemeSwitch() {
</> </>
) )
} }
export default memo(ThemeSwitch)

View File

@ -8,9 +8,12 @@ const query = graphql`
label label
picture { picture {
childImageSharp { childImageSharp {
fixed(width: 256, height: 256) { gatsbyImageData(
...GatsbyImageSharpFixed_withWebp_noBase64 width: 256
} height: 256
placeholder: NONE
layout: FIXED
)
} }
} }
email email

View File

@ -1,4 +1,4 @@
import React, { memo } from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Link, graphql } from 'gatsby' import { Link, graphql } from 'gatsby'
import shortid from 'shortid' import shortid from 'shortid'
@ -41,7 +41,7 @@ function Project({ node, images }) {
<article className={styleProject} key={slug}> <article className={styleProject} key={slug}>
<Link to={slug}> <Link to={slug}>
<h1 className={styleTitle}>{title}</h1> <h1 className={styleTitle}>{title}</h1>
<ProjectImage fluid={img.childImageSharp.fluid} alt={title} /> <ProjectImage image={img.childImageSharp.gatsbyImageData} alt={title} />
{imageCount > 1 && ( {imageCount > 1 && (
<small <small
@ -61,7 +61,7 @@ Home.propTypes = {
pageContext: PropTypes.object.isRequired pageContext: PropTypes.object.isRequired
} }
function Home({ data, pageContext }) { export default function Home({ data, pageContext }) {
const projects = data.allProjectsYaml.edges const projects = data.allProjectsYaml.edges
const images = data.projectImageFiles.edges const images = data.projectImageFiles.edges
@ -80,8 +80,6 @@ function Home({ data, pageContext }) {
) )
} }
export default memo(Home)
export const IndexQuery = graphql` export const IndexQuery = graphql`
query { query {
allProjectsYaml { allProjectsYaml {
@ -91,9 +89,7 @@ export const IndexQuery = graphql`
slug slug
img { img {
childImageSharp { childImageSharp {
fluid(maxWidth: 980, quality: 85) { gatsbyImageData(layout: CONSTRAINED, width: 980, quality: 85)
...GatsbyImageSharpFluid_withWebp
}
} }
} }
} }

View File

@ -1,4 +1,4 @@
import React, { PureComponent } from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import FullWidth from '../components/atoms/FullWidth' import FullWidth from '../components/atoms/FullWidth'
@ -14,76 +14,67 @@ import {
description description
} from './{ProjectsYaml.slug}.module.css' } from './{ProjectsYaml.slug}.module.css'
class ProjectMeta extends PureComponent { function ProjectMeta({ links, techstack }) {
static propTypes = { return (
links: PropTypes.array, <footer className={meta}>
techstack: PropTypes.array {!!links && <ProjectLinks links={links} />}
} {!!techstack && <ProjectTechstack techstack={techstack} />}
</footer>
render() { )
const { links, techstack } = this.props
return (
<footer className={meta}>
{!!links && <ProjectLinks links={links} />}
{!!techstack && <ProjectTechstack techstack={techstack} />}
</footer>
)
}
} }
class ProjectImages extends PureComponent { ProjectMeta.propTypes = {
static propTypes = { links: PropTypes.array,
projectImages: PropTypes.array, techstack: PropTypes.array
title: PropTypes.string
}
render() {
return (
<FullWidth>
{this.props.projectImages.map(({ node }) => (
<div className={imageWrap} key={node.id}>
<ProjectImage fluid={node.fluid} alt={this.props.title} />
</div>
))}
</FullWidth>
)
}
} }
export default class Project extends PureComponent { function ProjectImages({ projectImages, title }) {
static propTypes = { return (
data: PropTypes.object.isRequired, <FullWidth>
location: PropTypes.object.isRequired {projectImages.map(({ node }) => (
} <div className={imageWrap} key={node.id}>
<ProjectImage image={node.gatsbyImageData} alt={title} />
</div>
))}
</FullWidth>
)
}
render() { ProjectImages.propTypes = {
const { data } = this.props projectImages: PropTypes.array,
const project = data.projectsYaml title: PropTypes.string
const projectImages = data.projectImages.edges }
const descriptionHtml = data.projectsYaml.fields.descriptionHtml
const { title, links, techstack } = project
return ( export default function Project({ data }) {
<> const project = data.projectsYaml
<SEO project={project} /> const projectImages = data.projectImages.edges
const descriptionHtml = data.projectsYaml.fields.descriptionHtml
const { title, links, techstack } = project
<article> return (
<header> <>
<h1 className={headerTitle}>{title}</h1> <SEO project={project} />
</header>
<div
className={description}
dangerouslySetInnerHTML={{ __html: descriptionHtml }}
/>
<ProjectImages projectImages={projectImages} title={title} />
<ProjectMeta links={links} techstack={techstack} />
</article>
<ProjectNav currentSlug={project.slug} /> <article>
</> <header>
) <h1 className={headerTitle}>{title}</h1>
} </header>
<div
className={description}
dangerouslySetInnerHTML={{ __html: descriptionHtml }}
/>
<ProjectImages projectImages={projectImages} title={title} />
<ProjectMeta links={links} techstack={techstack} />
</article>
<ProjectNav currentSlug={project.slug} />
</>
)
}
Project.propTypes = {
data: PropTypes.object.isRequired,
location: PropTypes.object.isRequired
} }
export const projectQuery = graphql` export const projectQuery = graphql`

View File

@ -1,13 +1,14 @@
import '@testing-library/jest-dom/extend-expect' import '@testing-library/jest-dom/extend-expect'
import 'jest-canvas-mock' import 'jest-canvas-mock'
import { StaticQuery, useStaticQuery } from 'gatsby' import { StaticQuery, useStaticQuery } from 'gatsby'
import { getSrc } from 'gatsby-plugin-image'
import meta from './__fixtures__/meta.json' import meta from './__fixtures__/meta.json'
import resume from './__fixtures__/resume.json' import resume from './__fixtures__/resume.json'
import projects from './__fixtures__/projects.json' import projects from './__fixtures__/projects.json'
beforeAll(() => { beforeAll(() => {
const photoSrc = resume.contentJson.basics.picture.childImageSharp.fixed.src const photoSrc = getSrc(resume.contentJson.basics.picture)
const dataMock = { const dataMock = {
...meta, ...meta,
...resume, ...resume,