menu

Gatsby.js

Fast in every way that matters. Gatsby is a free and open source framework based on React that helps developers build blazing fast websites and apps.

Channels
# All channels
view-forward
# General
view-forward
# I Made This
view-forward
# Meta
view-forward
# Themes
view-forward
Team

Using Variables in a StaticQuery

December 13, 2018 at 10:05pm

Using Variables in a StaticQuery

December 13, 2018 at 10:05pm
Hey Folks - I'm using gatsby-image in my latest project and I'm finding it a bit cumbersome to have to write a whole query just to display an image. I would love to just have a component that I pass a src to and it does it all under the hood.
So - I'm writing a component with StaticQuery that looks like this:
import React from 'react';
import Img from 'gatsby-image';
import { StaticQuery, graphql } from 'gatsby';
function renderImage({ file }) {
return <Img fluid={file.childImageSharp.fluid} />
}
const MyImg = function (props) {
return <StaticQuery
query={graphql`
query {
file(relativePath: { eq: "wes-and-scott.jpg" }) {
childImageSharp {
fluid(maxWidth: 1000) {
...GatsbyImageSharpFluid
}
}
}
}
`}
render={renderImage}
/>
}
export default MyImg;
Now that works amazingly well, BUT I can't make the filename dynamic.
I read in the docs that Static Query can't take variables - only pages. But I don't want my images to be associated with a page - I want to use this component anywhere I want - like a regular img tag.
I tried string interpolation and that doesn't work.
Any way to get around this? Am I thinking about this in the wrong way?
Show previous messages

December 14, 2018 at 2:44pm
Hey Wes, what I've done, without seeing too much of a performance hit, seems to be exactly what you're suggesting: namely, create a component that queries all image nodes in a specific location and filter the results, finding match and returning it (or a default placeholder, if no match is found).
  • reply
  • like
In order to speed things up, I've broken the images into groups (maybe I have Bio images, Cover images, and Dog images... I'd have <DogImage /> <BioImage /> and <CoverImage />).
  • reply
  • like
And they point to images/dogs, images/bios, images/covers
  • reply
  • like
I'd like to look into the performance implications of this, too. I'm wondering if, since to my understanding the first render and the StaticQuery itself happens on build, and not browser-side, the hit would even be noticeable.
Edited
  • reply
  • like
just as a follow up, I set up the following netlify to test this: https://dazzling-bohr-1d9d3d.netlify.com/ using 200 random unsplash images.
  • reply
  • like
The homepage uses 200 components, each with its own StaticQuery and /page-2/ uses a single component with a single StaticQuery, being filtered.
  • reply
  • like
Not sure how much to trust the Chrome profiler, but here's the first page's snapshot
  • reply
  • like
  • reply
  • like
And the second
  • reply
  • like
  • reply
  • like
Thanks for doing that. So from your results, what do they mean?
  • reply
  • like
No problem! I'm not an expert here, but I would say that it means that it means that using a reusable component is worth it! The browser doesn't spend any extra time running the component logic (filtering the 200 images 200 times).
  • reply
  • like
first off, thanks for putting in that work. But to be honest, it kind of misses my point - which is reusing the same image component for multiple pages. Where the individual StaticQuerys would only load exactly the image data that is required for that page, while the reusable component in question would load all images even if they're not used on that page.
  • reply
  • like
Exactly. Also, my main concern was more about overfetching than memory usage. So perhaps you could compare the data usage or loading time on a simulated 3G network between the two approaches.
  • reply
  • like
So you are right. Check out https://dazzling-bohr-1d9d3d.netlify.com/page-4/ which uses the reuseable component. If you look at the js being loaded, you will see the metadata and the base64 for the smallest blurry image being loaded for all 200 images.
  • reply
  • like
Compared to https://dazzling-bohr-1d9d3d.netlify.com/page-3 which uses the one-off component
  • reply
  • like
To give this a number: page-3 (one-time component) is 166KB for all requests
  • reply
  • like
and page-4 (reuseable component) is 219KB transferred total
  • reply
  • like
Which is, to be fair, a 30% increase, even though it's "only" 53KB
Edited
  • reply
  • like
That said, if you're using another source like MDX or MD, then you can use the plugins which will extract just the images being used for those pages.
  • reply
  • like

December 15, 2018 at 1:55am
Yeah, the main question with this technique is how many extra images you're loading metadata for. This can get quite large e.g. https://www.gatsbyjs.org/showcase/ used to load preview images in base64 for every showcase site and a while ago (before I disabled it) it was adding ~250kb extra data which caused a noticeable slowdown in time-to-interactive.
like-fill
1
  • reply
  • like
As long as you're under say ~200 images, you're probably fine
  • reply
  • like
Explored a possible solution to this https://github.com/gatsbyjs/gatsby/issues/10482
like-fill
6
  • reply
  • like
Show more messages