javascript - Gatsbyjs 页面生成 |最佳实践

标签 javascript reactjs gatsby wordpress-rest-api

我正在使用 headless WordPress 作为数据源开发 Gatsbyjs 网络。我不想在/pages 中静态生成所有页面,而是在 im gatsby-node.js 中通过 allPages/allPosts 查询进行映射,并使用 createPage API 将数据发送到页面/帖子模板。

但是我的页面有点复杂,它们似乎需要非常不同的查询(acf..)

这里的最佳实践是什么?我应该为每个页面创建一个模板并将数据直接映射到其中吗?

最佳答案

是的,你说到点子上了。您必须为要生成的每种类型的页面生成模板/页面。

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,
      },
    })
  })
}

组件将定义数据的可用位置以及将使用哪个模板/页面/组件。

如果您想使用不同的模板而不是 /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.jstags.js 可以在 /blog-post/postSlug 中找到/tag/tagPath.

Promise 用例

如果你有一个小型网站或项目,前面的情况可能可行,但如果你的项目规模扩大,在这么多行中查找信息就变得很 hell 。所以我用来创建 promises来存储该信息。在我的 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;

请注意,代码可以通过多种方式重构,只是为了展示您能够执行的操作的另一种方法。

我认为 Promise 方式更加语义化和简洁,但取决于您在每种情况下使用您需要的任何内容。

引用文献:

  1. First query
  2. Second query

关于javascript - Gatsbyjs 页面生成 |最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60851427/

相关文章:

javascript - 对类数组对象进行排序 Angular

javascript - 在灯箱上打印图像

javascript - 如何使 <object> 视频适合父容器的宽度和高度

reactjs - useContext() 不应该只用于低频率更新吗? (mobx-react-lite)

gatsby - 人们如何在现实世界中使用 gatsby-image?

javascript - 动态添加文件以请求发布

javascript - react 错误 : (function) is not defined at HTMLButtonElement. onclick

javascript - 当我使用 for 或 while 循环时,我的应用程序崩溃

javascript - 为什么我的 gatsby 应用程序显示 Unknown argument 'frontmatter' 错误?

css - 如何将 React Bootstrap 与 Gatsby 集成