Синтаксис GraphQL для доступа к файлу по относительному пути

GatsbyJS документы дает этот пример для доступа к файлу по относительному пути с GraphQL:

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

Я просто не могу заставить это работать, и я не знаю, почему. Я пробовал всевозможные синтаксисы, но запрос всегда возвращает null для имени файла. Это моя последняя попытка в GraphяQL:

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

Что мне не хватает? Как я могу получить доступ к файлу по относительному пути?

Изменить после прочтения ответа:

В моем gatsby-config.js есть несколько путей, доступных для запросов:

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

Когда я делаю запрос для pic.jpg (вместо images/pic.jpg), как Гэтсби узнает, что я хочу images/pic.jpg вместо posts/pic.jpg? Как это однозначно определяет путь?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
12
0
5 469
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Поле relativePath узла File относится к каталогу, который вы указали в gatsby-source-filesystem.

Например, скажем, у меня есть такая структура каталогов:

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

А в моем gatsby-config.js

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

Файлы внутри dirA будут иметь следующий relativePath:

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

Я могу запросить fileC следующим образом:

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

Итак, в вашем случае вы можете указать gatsby-source-filesystem на родительский каталог html.js, и он должен быть доступен для запросов.


Получить уникальный файл

Если у меня есть следующая структура:

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

И укажите gatsby-source-filesystem на них обоих, теперь есть 2 файловых узла с одним и тем же relativePath (index.md).

В этом случае небезопасно выполнять следующий запрос:

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

Потому что он вернет первый узел файла, который удовлетворяет условию фильтра (я не уверен, как Гэтсби определяет порядок файлов, если кто-то знает, поделитесь!). Будет безопаснее добавить несколько дополнительных уникальных фильтров.

Например, когда я устанавливаю gatsby-source-filesystem, я могу указать свойство name. Этот name будет храниться в поле sourceInstanceName на узлах файлов.

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

Я могу запросить это так:

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

Я думаю, что комбинации sourceInstanceName и relativePath достаточно, чтобы файл был уникальным.

Кроме того, вы также можете запросить узел File по его absolutePath. Это гарантирует, что файл уникален, хотя вам все равно нужно сообщить gatsby-source-filesystem, где находится файл.

Если вы хотите увидеть все файлы с одинаковым relativePath, этот запрос будет выполняться:

query {
  allFile(filter: {
    relativePath: { eq: "index.md" }
  }) {
    edges {
      node { 
        id
      }
    } 
  }
}

Большое спасибо, еще раз! Это работает, хотя мне все еще интересно, как это однозначно определяет путь? Я отредактировал ОП, чтобы уточнить, что я имею в виду под этим вопросом.

Atte Juvonen 06.02.2019 15:47

@AtteJuvonen Привет, Атте! Я обновил ответ, чтобы ответить на отредактированный вопрос. Короче говоря, если вы полагаетесь только на relativePath, Gatsby не будет знать, какой файл вам нужен, и просто вернет первый найденный файл. Вам придется добавить дополнительные фильтры, чтобы убедиться, что файл уникален.

Derek Nguyen 06.02.2019 16:04

Кроме того, вы также можете запросить узел File по его полю absolutePath, и в этом случае вам не нужно будет передавать дополнительные фильтры.

Derek Nguyen 06.02.2019 17:56

Это действительно хороший ответ, требующий комментария, а не просто голосования. :-) Кажется, это не ясно указано в Страница плагина Gatsby gatsby-source-filesystem или его репозиторий GitHub. Спасибо.

T.J. Crowder 29.06.2020 14:09

Отличный ответ!

AleksandrH 19.12.2020 15:53

Что меня зацепило, так это то, что для Эта проблема вам нужно перезапустить gatsby develop для обновления данных GraphQL (т.е. после того, как вы настроите relativePath).

Это можно решить:

  • Запуск Гэтсби с ENABLE_GATSBY_REFRESH_ENDPOINT=true gatsby develop
  • Запуск curl -X POST localhost:8000/__refresh в отдельном терминале каждый раз, когда вы хотите обновить данные

Другие вопросы по теме