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:
parent
8da788e4d2
commit
9493b9d2ef
@ -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.
|
||||||
|
|
||||||
|
@ -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
28206
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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",
|
||||||
|
@ -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}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -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 = {
|
||||||
|
@ -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>
|
||||||
|
@ -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)
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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`
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user