I’m thinking of using Gatsby-Image for my next project and has been playing around with it a little.
I got it to work on my test project but then I came up with a u
I've been searching for this answer as well. Hopefully this answers your question:
import React from 'react';
import { StaticQuery, graphql } from 'gatsby';
import Img from 'gatsby-image';
// Note: You can change "images" to whatever you'd like.
const Image = props => (
<StaticQuery
query={graphql`
query {
images: allFile {
edges {
node {
relativePath
name
childImageSharp {
fluid(maxWidth: 600) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`}
render={data => {
const image = data.images.edges.find(n => {
return n.node.relativePath.includes(props.filename);
});
if (!image) {
return null;
}
//const imageSizes = image.node.childImageSharp.sizes; sizes={imageSizes}
return <Img alt={props.alt} fluid={image.node.childImageSharp.fluid} />;
}}
/>
);
export default Image;
Using the image:
import Image from '../components/Image';
<div style={{ maxWidth: `300px` }}>
<Image alt="Gatsby in Space" filename="gatsby-astronaut.png" />
</div>
Because StaticQuery doesn't support string interpolation in its template literal, we can't really pass it any props. Instead we will try and handle check for props in the StaticQuery's Render portion.
I'm not 100% sure if this affects compiling time since we are scanning all images. If it does, please let me know!
Update: If you have many images, bundle size can get quite large as this solution does scan ALL images.
You can adjust the code to show a placeholder image if no props are passed.
That said, there is another way you could tackle this but with a bit more work/code.
Unfortunately from what I can gather the best solution is to write out individual js files for images.
In @RodrigoLeon's approach, it will cause bundle size to increase DRAMATICALLY. Especially if say you have more than 50 images. Because anytime you use this and loop through all images you create references to them in the component file. So I would not recommend doing it this way.
The site I am building is an e-commerce platform with thousands of images (for all the products). This presented a major issue with using gatsby which is querying images. For a long time, I had a component that queried all images and matched them up to their respective product. (Like proposed in this ) This is highly inefficient, throwing warnings about the duration of the query.
An alternate to this is the attach the imageFile to the product on the data level, rather than when trying to render.
src/gatsby-api/create-resolvers/index.js
const resolvers = {
AWSAppSync_Product: {
imageFile: {
type: 'File',
resolve: async (source, args, context, info) => {
const node = await context.nodeModel.runQuery({
query: {
filter: {
Key: { eq: source.image1 }
}
},
type: 'S3Object',
firstOnly: true
});
if (node && node.imageFile) return node.imageFile;
}
},
},
}
module.exports = {
resolvers
}
gatsby-node.js
exports.createResolvers = async ({ createResolvers }) => {
createResolvers(resolvers)
}
src/components/image/index.js
import React from 'react'
import Img from 'gatsby-image'
export const Image = props => {
if (props.imageFile && props.imageFile.childImageSharp && props.imageFile.childImageSharp.fluid) {
return <Img className={props.imgClassName} alt={props.alt} fluid={props.imageFile.childImageSharp.fluid} />;
}
};
Then use it like:
<Image
imageFile={product.imageFile}
alt=""
/>
AWSAppSync_Product
is the type of node I am attaching my File to. (which can be found in the graphql playground on localhost). The resolve will match the Key
of the S3Object
with image1
(which is a string) on the product. This allows me to directly use the product images without having to run a query inside the image component.
In my opinion, this is a valuable piece of information once you wrap your head around it and it certainly has helped me a lot.