Гэтсби js Генерация страниц | Лучшие практики - PullRequest
1 голос
/ 25 марта 2020

Я работаю над сетью Gatsby js с безголовым WordPress в качестве источника данных. Я не хочу генерировать все страницы статически в / pages, но вместо этого в im gatsby- node.js отображение через запросы allPages / allPosts и отправка данных на шаблон page / post с использованием createPage API.

Но мои страницы довольно сложные, они, кажется, нуждаются в совершенно разных запросах (acf ..)

Что было бы лучшим вариантом здесь? Должен ли я создать шаблон для каждой страницы и отобразить данные непосредственно на них?

1 Ответ

2 голосов
/ 25 марта 2020

Да, вы попали в гвоздь. Вы должны сгенерировать шаблоны / страницы для каждого типа страницы, которую вы хотите сгенерировать.

TL; DR

Вам нужно только создать различные действия createPage и указать их на разных шаблонах / страницах. , Например:

createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/blog-post.js`),
      context: {
        slug: node.fields.slug,
      },
    })

и

 createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/tags.js`),
      context: {
        slug: node.fields.slug,
      },
    })

Длинная версия

Стандартный вариант использования

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query {
      allMarkdownRemark {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `)
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/blog-post.js`),
      context: {
        slug: node.fields.slug,
      },
    })
  })
}

component определит, где будут доступны данные для использования и какой шаблон / страница / компонент будет использоваться.

Если вы хотите использовать другой шаблон вместо /blog-post, вам нужно создать другое действие createPage , Примерно так:

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

  return graphql(`
    {
      allMarkdownRemark(limit: 1000) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              tags
              templateKey
            }
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      result.errors.forEach(e => console.error(e.toString()))
      return Promise.reject(result.errors)
    }

    const posts = result.data.allMarkdownRemark.edges

    posts.forEach(edge => {
      const id = edge.node.id
      createPage({
        path: edge.node.fields.slug,
        tags: edge.node.frontmatter.tags,
        component: path.resolve(
          `src/templates/blog-post.js`
        ),
        // additional data can be passed via context
        context: {
          id,
        },
      })
    })

    // Tag pages:
    let tags = []
    // Iterate through each post, putting all found tags into `tags`
    posts.forEach(edge => {
      if (_.get(edge, `node.frontmatter.tags`)) {
        tags = tags.concat(edge.node.frontmatter.tags)
      }
    })
    // Eliminate duplicate tags
    tags = _.uniq(tags)

    // Make tag pages
    tags.forEach(tag => {
      const tagPath = `/tags/${_.kebabCase(tag)}/`

      createPage({
        path: tagPath,
        component: path.resolve(`src/templates/tags.js`),
        context: {
          tag,
        },
      })
    })
  })
}

Не вдаваясь в подробности того, что он делает или как (если вам нужно, я могу детализировать ответ), важно то, что вы можете использовать действие createPage, чтобы определить, сколько страницы, данные и компоненты, которые вам нужны. В этом случае blog-post.js и tags.js, которые будут найдены под /blog-post/postSlug и /tag/tagPath.

Вариант использования Promise

Если у вас есть маленький сайт или проект, предыдущий случай может сработать, но если ваш проект растет, то становится чертовски найти информацию среди такого количества строк. Поэтому я использую для создания обещаний для хранения этой информации. В моем gatsby-node:

const postsBuilder = require("./src/build/postsBuilder");
const tagsBuilder = require("./src/build/tagsBuilder");

exports.createPages = async ({graphql, actions}) => {
  await Promise.all(
    [
      postBuilder(graphql, actions),
      tagsBuilder(graphql, actions)
    ]
  );
};

Затем, в одном из этих конструкторов:

const path = require('path')

async function postsBuilder(graphql, actions) {
  const {createPage} = actions;

  const postsQuery= await graphql(`
     {
      allMarkdownRemark(limit: 1000) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              tags
              templateKey
            }
          }
        }
      }
    }`);

  const resultForms = postsQuery.data.allMarkdownRemark.edges;

  resultForms.map(node => {
      createPage({
        path: node.node.url + '/',
        component: whateverYouNeed,
        context: {
          name: node.node.name,
          url: node.node.url
        },
      })
  });
}

module.exports = postsBuilder;

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

Я думаю, что обещанный способ намного более семантичен c и чист, но вы должны использовать все, что вам нужно в каждом случае.

Ссылки:

  1. Первый запрос
  2. Второй запрос
...