Gatsby`createPage`正在生成具有相同数据的页面

时间:2019-09-02 21:37:56

标签: javascript node.js reactjs graphql gatsby

gatsby-config.js配置为从./content目录获取所有markdown文件。

ServicePostBlogPost模板从./src/content/services./src/content/blog个目录。

gatsby-node.js基于在./src/content/中设置的templateKey对数据进行排序 markdown文件的最重要内容,并将其传递给createPage,后者生成页面 在/services/service-name/blog/blog-article-name网址上。

我遇到的问题是所有/services/service-name/blog/blog-article-name页 会使用来自./services/./blog/目录的第一篇文章中的数据生成。

gatsby-config.js

const proxy = require('http-proxy-middleware')

module.exports = {
  siteMetadata: {
    title: 'Gatsby + Netlify CMS Starter',
    description:
      'This repo contains an example business website that is built with Gatsby, and Netlify CMS.It follows the JAMstack architecture by using Git as a single source of truth, and Netlify for continuous deployment, and CDN distribution.',
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sass',
    {
      // keep as first gatsby-source-filesystem plugin for gatsby image support
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/static/img`,
        name: 'uploads',
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/content`,
        name: 'content',
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/img`,
        name: 'images',
      },
    },
    'gatsby-plugin-sharp',
    'gatsby-transformer-sharp',
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        plugins: [
          {
            resolve: 'gatsby-remark-relative-images',
            options: {
              name: 'uploads',
            },
          },
          {
            resolve: 'gatsby-remark-images',
            options: {
              // It's important to specify the maxWidth (in pixels) of
              // the content container as this plugin uses this as the
              // base for generating different widths of each image.
              maxWidth: 2048,
            },
          },
          {
            resolve: 'gatsby-remark-copy-linked-files',
            options: {
              destinationDir: 'static',
            },
          },
        ],
      },
    },
    {
      resolve: 'gatsby-plugin-netlify-cms',
      options: {
        modulePath: `${__dirname}/src/cms/cms.js`,
      },
    },
    {
      resolve: 'gatsby-plugin-purgecss', // purges all unused/unreferenced css rules
      options: {
        develop: true, // Activates purging in npm run develop
        purgeOnly: ['/all.sass'], // applies purging only on the bulma css file
      },
    }, // must be after other CSS plugins
    'gatsby-plugin-netlify', // make sure to keep it last in the array
  ],
  // for avoiding CORS while developing Netlify Functions locally
  // read more: https://www.gatsbyjs.org/docs/api-proxy/#advanced-proxying
  developMiddleware: app => {
    app.use(
      '/.netlify/functions/',
      proxy({
        target: 'http://localhost:9000',
        pathRewrite: {
          '/.netlify/functions/': '',
        },
      })
    )
  }
}

gatsby-node.js

const _ = require('lodash')
const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')
const { fmImagesToRelative } = require('gatsby-remark-relative-images')

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

  const blogs = await graphql(`
    {
      blogs: allMarkdownRemark(
        limit: 1000
        filter: { frontmatter: { templateKey: { eq: "blog-post" } } }
        sort: {
          fields: [frontmatter___date]
          order: [DESC]
        }
      ) {
        edges {
          node {
            id
            fields {
              slug
            }
            html
            frontmatter {
              title
              templateKey
              date
            }
          }
        }
      }
    }
  `)

  const BlogPostTemplate = path.resolve(`src/templates/BlogPost.js`)
  blogs.data.blogs.edges.forEach(({ node }) => {

    createPage({
      path: node.fields.slug,
      component: BlogPostTemplate,
      context: {},
    });
  });

  const services = await graphql(`
    {
      services: allMarkdownRemark(
        limit: 1000
        filter: { frontmatter: { templateKey: { eq: "service-post" } } }
      ) {
        edges {
          node {
            id
            fields {
              slug
            }
            html
            frontmatter {
              title
              templateKey
            }
          }
        }
      }
    }
  `)

  const ServicePostTemplate = path.resolve(`src/templates/ServicePost.js`)
  services.data.services.edges.forEach(({ node }) => {
    createPage({
      path: node.fields.slug,
      component: ServicePostTemplate,
    });
  });
}

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions
  fmImagesToRelative(node) // convert image paths for gatsby images

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    createNodeField({
      name: `slug`,
      node,
      value,
    })
  }
}

./src/templates/BlogPost.js

import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import { graphql } from 'gatsby'
import Layout from '../components/Layout'
import Content, { HTMLContent } from '../components/Content'

export const BlogPostTemplate = ({
  content,
  contentComponent,
  description,
  title,
  helmet,
}) => {
  const PostContent = contentComponent || Content

  return (
    <section>
      {helmet || ''}
        <h1>
          {title}
        </h1>

        Blog post template

        <p>{description}</p>
        <PostContent content={content} />
    </section>
  )
}

BlogPostTemplate.propTypes = {
  content: PropTypes.node.isRequired,
  contentComponent: PropTypes.func,
  title: PropTypes.string,
  helmet: PropTypes.object,
}

const BlogPost = ({ data }) => {
  // console.log('Blog Post Data', JSON.stringify(data))

  const { markdownRemark: post } = data

  return (
    <Layout>
      <BlogPostTemplate
        content={post.html}
        contentComponent={HTMLContent}
        helmet={
          <Helmet titleTemplate="%s | Blog">
            <title>{`${post.frontmatter.title}`}</title>
          </Helmet>
        }
        title={post.frontmatter.title}
      />
    </Layout>
  )
}

BlogPost.propTypes = {
  data: PropTypes.shape({
    markdownRemark: PropTypes.object,
  }),
}

export default BlogPost

export const pageQuery = graphql`
  query BlogPostByID {
    markdownRemark(frontmatter: { templateKey: { eq: "blog-post" } }) {
      id
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        title
      }
    }
  }
`

./src/content/blog/blog-post-1.md

---
templateKey: blog-post
title: Blog post 1 title
date: 2014-12-17T15:04:10.000Z
---

Blog post 1 body

1 个答案:

答案 0 :(得分:0)

您已解决此问题吗?

您是否曾尝试在createPage时将节点放入上下文中

gatsby-node.js

    createPage({
          path: node.fields.slug,
          component: BlogPostTemplate,
          context: {node}, // adding node in here and then pulling it as a 
                               // props everytime you create a page?
        });

./ src / templates / BlogPost.js

    export const BlogPostTemplate = ({node}) => {

 <h1>{node.context.node.frontmatter.title}<h1> // sorry don't know what the extact api route would be but i think tis something like this. just double check with a console.log

}

,其余的可能会扩展查询以在创建页面之前获取所有数据字段。

我不知道这是否对您有用,但我认为值得一提。