Gatsby: How can I use gatsby-image image optimisation inside a nested query?

Created on 12 Sep 2018  路  9Comments  路  Source: gatsbyjs/gatsby

Summary

Relevant information

I'm using gatsby-transformer-yaml to load some data from a file, portfolio.yaml:

- item:
  image: portfolio/trausing.png
  # ...

As shown, each item contains an image field, which is a path to an image.

This is fine and I can easily query this with the following:

query {
  portfolio: allPortfolioYaml {
    edges {
      node {
        name
        caseStudy
        description
        image
        siteLink
        year
        skillsUsed
      }
    }
  }
}

The problem is I'm using gatsby-image to handle image optimisation, which I want to apply to the image field.

I'm doing this with another query in my app, which looks like this:

query {
  avatar: file(relativePath: { eq: "daniel-spajic-avatar.png" }) {
    childImageSharp {
      resolutions(width: 160, height: 160) {
        ...GatsbyImageSharpResolutions_withWebp_tracedSVG
      }
    }
  }
}

This works because file is a field the root query object. But I can't do it with my query on the YAML file, such as with the following:

query {
  portfolio: allPortfolioYaml {
    edges {
      node {
        name
        caseStudy
        description
        siteLink
        year
        skillsUsed
        image: file(relativePath: { eq: image }) {
          childImageSharp {
            resolutions(width: 160, height: 160) {
              originalName
            }
          }
        }
      }
    }
  }
}

Doing so throws the following error Cannot query field "file" on type "PortfolioYaml".

So in this case how can I use gatsby-image's image optimisation on the image field queried from portfolio.yaml? Or this there another way to achieve what I'm trying to do?

I've been messing around with this, and have also tried looking online and reading the docs, but I haven't been able to figure it out.

File contents (if changed)

gatsby-config.js:

const cssnext = require('postcss-cssnext');

module.exports = {
  siteMetadata: {
    title: 'Daniel Spajic | Front-end engineer with a full-stack skillset',
    siteUrl: 'https://danieljs.tech',
    description:
      'Front-end engineer specialising in building robust web apps with React.js',
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-eslint',
    {
      resolve: 'gatsby-plugin-manifest',
      options: {
        name: 'Daniel Spajic',
        short_name: 'Daniel Spajic',
        start_url: '/',
        background_color: '#f8f9fa',
        theme_color: '#ff7e33',
        display: 'minimal-ui',
        icon: `${__dirname}/src/images/icon.png`,
      },
    },
    'gatsby-plugin-offline',
    'gatsby-plugin-sitemap',
    'gatsby-transformer-sharp',
    'gatsby-plugin-sharp',
    'gatsby-transformer-yaml',
    {
      resolve: 'gatsby-plugin-resolve-src',
      options: {
        addSassLoader: false,
      },
    },
    {
      resolve: 'gatsby-plugin-postcss-sass',
      options: {
        postCssPlugins: [cssnext()],
        precision: 8,
        includePaths: ['src/scss'],
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'content',
        path: `${__dirname}/src/content`,
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'images',
        path: `${__dirname}/src/images`,
      },
    },
    {
      resolve: 'gatsby-plugin-google-analytics',
      options: {
        trackingId: 'UA-125642949-1',
        respectDNT: true,
      },
    },
  ],
};

package.json:

{
  "name": "portfolio",
  "private": true,
  "description": "Daniel Spajic's portfolio",
  "scripts": {
    "build": "gatsby build",
    "develop": "gatsby develop",
    "test": "jest",
    "test:watch": "yarn run test -- --watch"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "jsx"
    ],
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|md)$": "<rootDir>/src/__mocks__/fileMock.js",
      "\\.(scss)$": "identity-obj-proxy",
      "^components$": "src/components"
    },
    "setupFiles": [
      "<rootDir>/src/setupTests.js",
      "<rootDir>/src/shimTests.js"
    ],
    "testEnvironment": "jsdom",
    "testPathIgnorePatterns": [
      ".cache"
    ],
    "testURL": "http://localhost/"
  },
  "dependencies": {
    "bootstrap": "^4.1.3",
    "classnames": "^2.2.6",
    "gatsby": "^1.9.277",
    "gatsby-image": "^1.0.55",
    "gatsby-link": "^1.6.46",
    "gatsby-plugin-eslint": "^1.0.3",
    "gatsby-plugin-google-analytics": "^1.0.31",
    "gatsby-plugin-manifest": "^1.0.27",
    "gatsby-plugin-offline": "^1.0.18",
    "gatsby-plugin-postcss-sass": "^1.0.22",
    "gatsby-plugin-react-helmet": "^2.0.11",
    "gatsby-plugin-resolve-src": "^1.1.4",
    "gatsby-plugin-sharp": "^1.6.48",
    "gatsby-plugin-sitemap": "^1.2.25",
    "gatsby-source-filesystem": "^1.5.39",
    "gatsby-transformer-sharp": "^1.6.27",
    "gatsby-transformer-yaml": "^1.5.18",
    "html-loader": "^0.5.5",
    "lodash": "^4.17.10",
    "markdown-loader": "^4.0.0",
    "react": "^16.4.2",
    "react-dom": "^16.4.2",
    "react-helmet": "^5.2.0",
    "react-plx": "^1.3.9",
    "reactstrap": "^6.3.1"
  },
  "devDependencies": {
    "babel-plugin-module-resolver": "^3.1.1",
    "enzyme": "^3.3.0",
    "enzyme-adapter-react-16": "^1.1.1",
    "eslint": "^5.3.0",
    "eslint-config-airbnb": "^17.0.0",
    "eslint-import-resolver-alias": "^1.1.1",
    "eslint-loader": "^2.1.0",
    "eslint-plugin-import": "^2.13.0",
    "eslint-plugin-jsx-a11y": "^6.1.1",
    "eslint-plugin-react": "^7.10.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^23.4.2",
    "postcss-cssnext": "^3.1.0",
    "react-router-dom": "^4.3.1",
    "stylelint": "^9.4.0",
    "stylelint-config-recommended-scss": "^3.2.0",
    "stylelint-scss": "^3.2.0"
  }
}

gatsby-node.js:

exports.modifyWebpackConfig = ({ config }) => {
  config.loader('markdown', {
    test: /\.md$/,
    loaders: ['html-loader', 'markdown-loader'],
  });

  return config;
};

gatsby-browser.js: N/A
gatsby-ssr.js: N/A

Most helpful comment

Great!

I think it is resolving the image path from the yaml path as a starting point. But I don't know exactly. It just looks like that.
So probably the image can be wherever you want, just the path in the yaml file has to point to that file relative to the yaml folder.

All 9 comments

Hey @dspacejs

did you try to change the query to something like this:

query {
  portfolio: allPortfolioYaml {
    edges {
      node {
        name
        caseStudy
        description
        siteLink
        year
        skillsUsed
        image {
          childImageSharp {
            resolutions(width: 160, height: 160) {
              originalName
            }
          }
        }
      }
    }
  }
}

You could try the query in GraphiQL (http://localhost:8000/___graphql) and hover over the "image" key. If it says that it is a File, then you're lucky and you can use childImageSharp directly unter the image key.

Is it working like that?

Excellent answer @zauni :)

That's exactly what I was going to say. The image _should_ be a node of type file so you should be able to use childImageSharp if the image ends in an image extension (jpg,jpeg,png,etc.)

I'm going to close this as answered, but please re-open or continue the conversation if you need more assistance. Thanks!!

@zauni thanks for the help, I just tried that query and it's throwing the following error:

Field "image" must not have a selection since type "String" has no subfields.

One potential solution I can think of is to create two separate queries; one for fetching the data from portfolio.yaml, the other for fetching the images using gatsby-image, and then merging the two results afterwards.

It's not ideal, but I can't think of how else to get this to work so it should do the job. I'll report back to share if it worked.

@DSchau can this issue please be reopened?

@dspacejs Can you try to change the filepath to a relative path inside the yaml file?

Maybe image: ./portfolio/trausing.png is working better.

@zauni thanks, I just tried that but the same error is present. It's linting the image field itself:

query error

@dspacejs Maybe your image is not in the same folder as the yaml file? Because if you put the image in the same folder (or in a subfolder) of the yaml file, the relative path is working and gatsby transforms the image path to a File type. Here are screenshots of my local test:

yaml

graphiql

@zauni yep that works perfectly for me, cheers!

But out of curiosity, why does it need to be in the same directory?

Great!

I think it is resolving the image path from the yaml path as a starting point. But I don't know exactly. It just looks like that.
So probably the image can be wherever you want, just the path in the yaml file has to point to that file relative to the yaml folder.

Was this page helpful?
0 / 5 - 0 ratings