Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL syntax to access file by relativepath

Tags:

graphql

gatsby

GatsbyJS docs give this example for accessing a file by relativepath with GraphQL:

export const query = graphql`
  query {
    fileName: file(relativePath: { eq: "images/myimage.jpg" }) {
      childImageSharp {
        fluid(maxWidth: 400, maxHeight: 250) {
          ...GatsbyImageSharpFluid
        }
      }
    }
  }
`

I just can't get this working and I don't know why. I've tried all kinds of different syntaxes but the query always returns null for filename. This is my most recent attempt in GraphiQL:

{
    fileName: file(relativePath: { eq: "./html.js" }) {
      id
    } 
}

What am I missing? How can I access a file by relative path?

Edit after reading the answer:

In my gatsby-config.js there are several paths set as queriable:

{
  resolve: `gatsby-source-filesystem`,
  options: {
    name: `images`,
    path: `${__dirname}/src/images/`
  }
},
{
  resolve: `gatsby-source-filesystem`,
  options: {
    path: `${__dirname}/content/posts/`,
    name: "posts"
  }
},
....

When I make a query for pic.jpg (instead of images/pic.jpg), how does Gatsby know I want images/pic.jpg instead of posts/pic.jpg? How is this uniquely defining a path?

like image 551
Atte Juvonen Avatar asked Feb 06 '19 10:02

Atte Juvonen


1 Answers

The relativePath field of a File node is relative to the directory you specified in gatsby-source-filesystem.

For example, say I have a directory structure like this:

root
  |--gatsby-config.js
  `--dirA
      |--fileA.md
      `--dirB
          |--fileB.md
          `--dirC
               `--fileC.md

And in my gatsby-config.js

{
  resolve: `gatsby-source-filesystem`
  options: {
    path: `${__dirname}/dirA`, <---- root/dirA
    name: `dir`,
  },
}

The files inside dirA will have the following relativePath:

File      |  relativePath
---------------------------------
fileA.md  |  'fileA.md'
---------------------------------
fileB.md  |  'dirB/fileB.md'
---------------------------------
fileC.md  |  'dirB/dirC/fileC.md'

I can query fileC like this:

query {
  fileName: file(relativePath: {
    eq: "dirB/dirC/fileC.md"
  }) {
    id
  }
}

So in your case, you can point gatsby-source-filesystem to the parent directory of html.js, and it should be queriable.


Get unique file

If I have the following structure:

root
  |--gatsby-config.js
  |--dirD
  |   `--index.md
  `--dirE
      `--index.md

And point gatsby-source-filesystem to both of them, now there're 2 File nodes with the same relativePath (index.md).

In this case, it's not safe to do the following query:

query {
  fileName: file(relativePath: {
    eq: "index.md"
  }) {
    id
  }
}

Because it will return the first File node that satisfies the filter condition (I'm not sure how gatsby decides file orders, if someone knows please share!). It'll be safer to add some additional unique filters.

For example, when I set gatsby-source-filesystem, I can specify a name property. This name will be stored in the sourceInstanceName field on File nodes.

{
  resolve: `gatsby-source-filesystem`,
  options: {
    path: `${__dirname}/dirE`,
    name: `dirE`,
  },
},

I can query it like so:

{
  file(
    relativePath: {
      eq: "index.md"
    },
    sourceInstanceName: {
      eq: "dirE"
    }
  ) {
    id
  }
}

I think the combination of sourceInstanceName and relativePath is enough to ensure the file is unique.

Alternatively, you can also query File node by its absolutePath. This'll guarantee the file is unique, though you still need to tell gatsby-source-filesystem where the file lives.

In case you want to see all files that has the same relativePath, this query will do:

query {
  allFile(filter: {
    relativePath: { eq: "index.md" }
  }) {
    edges {
      node { 
        id
      }
    } 
  }
}
like image 107
Derek Nguyen Avatar answered Nov 08 '22 22:11

Derek Nguyen