Создание второго шаблона блога на Gatsby - PullRequest
2 голосов
/ 17 октября 2019

Я пытаюсь создать второй шаблон блога на моем сайте Gatsby. Я только начинаю изучать Javascript, поэтому мне нужна помощь с файлом gatsby-node.js.

Я пытался дублировать каждую строку функций для создания второго шаблона блога, но каждый раз не получалось, поэтому, если кто-то сможет просмотреть мой код и предоставить правильные функции, это будет очень полезно.

У меня в настоящее время есть шаблон «статей», который успешно работает. Я хочу создать второй шаблон "проекты".

Это мой текущий файл gatsby-node.js, который вызывает только шаблон блога "статьи".


const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');

// Look at every node when it is created
exports.onCreateNode = ({node, getNode, actions}) => {
  // Check for markdown nodes
  const { createNodeField } = actions;
  if(node.internal.type === 'MarkdownRemark') {
    // Create a slug out of the markdown filepath name
    const slug = createFilePath({
      node,
      getNode,
      basePath: 'articles'
    });
    // Add the newly created slug to the node itself
    createNodeField({
      node,
      name: 'slug',
      value: `/article${slug}`
    });
  }
};

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return new Promise((resolve, reject) => {
    graphql(`
    {
      allMarkdownRemark {
      edges {
        node {
        fields {
          slug
        }
        }
      }
      }
    }
    `).then(result => {
    result.data.allMarkdownRemark.edges.forEach(({ node }) => {
      createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/article.js`),
      context: {
        // Data passed to context is available in page queries as GraphQL variables.
        slug: node.fields.slug,
      },
      })
    })
    resolve()
    })
  })
  };


Как настроитьэтот файл для вызова второго шаблона блога («проекты»)?

1 Ответ

2 голосов
/ 17 октября 2019

Для начала вам нужно получить обе ваши статьи, а также ваши проекты в запросе graphql, который вы получили. Вы можете использовать двоеточие, чтобы переименовать часть вашего запроса. Я добавил articles: перед вашей отметкой allMarkdown. В полученном JSON allMarkdownRemark теперь будет называться «article». Вы можете увидеть это в цикле forEach, который теперь перебирает «result.data.articles». Я также добавил запрос для нужного объекта «проекты». Переименование их в статьи и проекты позволяет нам легко перебирать каждую статью и каждый проект и создавать правильные страницы для этих объектов.

Запрос проектов теперь является точной копией запроса статей. На самом деле вы должны предоставить здесь запрос, который возвращает только проекты, но я не знаю, где у вас они есть. Затем создайте отдельные циклы для проектов и статей, в которых вы создаете правильные страницы.

exports.createPages = ({ graphql, actions }) => {
    const { createPage } = actions

    return new Promise((resolve, reject) => {
        graphql(`{
            articles: allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
            projects: allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
        }`).then(result => {

            // In this loop we only take the articles returned by the query, and
            // pass them to the src/templates/article.js component.
            result.data.articles.edges.forEach(({ node }) => {
                createPage({
                    // Rather than prepending every slug with '/article' in the
                    // createNodeField call, you can add it here to get more
                    // flexibility, and to allow different types to have different
                    // path prefixes.
                    path: `article/${node.fields.slug}`,
                    component: path.resolve(`./src/templates/article.js`),
                    context: {
                        slug: node.fields.slug,
                    },
                })
            })

            // In this loop we do the same thing, only with the projects this
            // time, and passing them to the project.js component I'm assuming
            // you have. I've prepended the path with 'project/' to separate
            // the projects from the articles.
            result.data.projects.edges.forEach(({ node }) => {
                createPage({
                    path: `project/${node.fields.slug}`,
                    component: path.resolve(`./src/templates/project.js`),
                    context: {
                        slug: node.fields.slug,
                    },
                })
            })

            resolve()
        })
    })
};

Я добавил некоторые отступы, чтобы было легче рассуждать. Возможно, по пути я допустил некоторые синтаксические ошибки, так что остерегайтесь этого.

Я заметил, что в вашем вызове onCreateNode вы устанавливаете порцию каждого файла уценки на «article / $ {slug}». Если ваши проекты также являются файлами уценки, вы не должны этого делать, потому что это также даст вашим файлам уценки, которые начинаются с '/ article'. В приведенном выше коде я установил правильный путь в вызове createPage, а не в createNodeField.

Одна вещь, которую вы должны иметь в виду, это то, что если у вас есть как ваши статьи, так и ваши проекты в качестве уценкифайлы, ваш запрос будет трудно разобрать их. Я обычно исправляю это, добавляя поле 'type' к frontmatter. Таким образом, в вашем случае вы добавите: type: article к frontmatter всех ваших статей и type: project для всех ваших проектов. Часть frontmatter - это часть в верхней части файла уценки, между тремя штриховыми линиями:

---
type: article
name: something
etc, etc...
---

Вы можете отфильтровать файлы уценки следующим образом:

graphql(`query {
      projects: allMarkdownRemark ( filter: {frontmatter: { type: { eq: "project" } } } ) {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }`);

Это вернеттолько файлы уценки, которые имеют тип проекта. Сделайте то же самое для ваших статей. Если вы используете Netlify CMS, вы можете добавить скрытое поле для автоматического добавления правильного типа, чтобы облегчить фильтрацию.

Возможно, вы захотите изменить обещание на асинхронный / ожидающий вызов. Это необязательно, но, на мой взгляд, это намного облегчает чтение. Посмотрите учебник Гэтсби здесь https://www.gatsbyjs.org/tutorial/part-seven/#creating-pages для примера async / await в API createPages.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...