How to create a second blog template to my Gatsby Site

蓝咒 提交于 2020-07-22 22:14:38

问题


My Gatsby Site need 2 blog templates:

  1. stories-template.js
  2. products.template.js

I have the stories-template running for my stories, but I am unsure how to tweak and change my existing codes in gatsby-node + products.template.js to make a second (different) template for my products.

I've tried all the solutions and past questions but no luck.

my code in gatsby-node.js:

const path = require('path');

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

const postTemplate = path.resolve('src/components/stories-template.js');

return graphql(`
{
    allMarkdownRemark {
        edges {
          node {
            html  
            id 
            frontmatter {
              path
              title
              author
              date
            }
          }
        }
      }
}
`).then(res => {
    if(res.errors) {
        return Promise.reject(res.errors)
    }

    res.data.allMarkdownRemark.edges.forEach(({ node }) => {
            createPage({
                path: node.frontmatter.path,
                component: postTemplate,
        })
    })
})
}

my code in stories-template.js:

import React from 'react'
import Layout from '../components/layout'


export default function Template({data}) {
const post = data.markdownRemark

return(<Layout>
    <div>
        <p>Stories</p>
        <br />
        <p>{post.frontmatter.title}</p>

        <div dangerouslySetInnerHTML={{__html: post.html}} />
    </div>
    </Layout>
)
}


export const postQuery = graphql`
query BlogPostByPath($path: String!) {
    markdownRemark(frontmatter: { path: {eq:$path}}){
        html
        frontmatter{
            path
            title
            date
            author
        }
    }
}
`

This works but now I want to create a different template for products in a products-template.js. Right now my products-template is basically just copied and pasted from my stories-template.

I for the life of me can't seem to figure this out.


回答1:


Like the first comment mentioned, more context might be necessary here, but I’ll give this a go. I think the problem is that regardless of the page, you’re telling the createPage function to use the postTemplate template component.

Gatsby doesn’t automatically read the templates in the template directory or anything like that, you need to add the logic for this yourself.

First, you’ll need to require your other template, for example:

const postTemplate = path.resolve('src/components/stories-template.js');
const productsTemplate = path.resolve('src/components/products-template.js');

Then, you need to decide when to use productsTemplate instead of postTemplate here:

createPage({
  path: node.frontmatter.path,
  component: postTemplate,
})

For example, maybe in each Markdown file, you have template YAML frontmatter:

createPage({
  path: node.frontmatter.path,
  component: node.frontmatter.template === 'product' ? productTemplate : postTemplate,
  })

Here’s how I try and approach it in a slightly more generic way on my own site. The URL structure determines the template: if it’s at /journal, it gets the Journal template component. If it’s at /shop, it gets the Shop template component.

This might not be quite enough to drop into your existing site, but hopefully it gets you closer:

const path = require('path')

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

  // I created an object to hold multiple templates.
  // In this case, my blog posts are at /journal and my
  // products are at /shop, so those are the keys I used here.
  // You might have a different system for determining what files
  // should use what template.
  const templates = {
    journal: path.resolve('src/templates/stories-template.js'),
    shop: path.resolve('src/templates/products-template.js'),
  }

  // Query for all Markdown “nodes”
  // Note I’m using a different GraphQL query, so you’ll need to replace this
  // with yours, or see if something with only the minimum requirements like
  // this works for you.
  return graphql(`
    {
      allMarkdownRemark {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      console.log(result.errors)
      reject(result.errors)
    }

    // Create pages from Markdown files
    result.data.allMarkdownRemark.edges.forEach(edge => {
      let slug = edge.node.fields.slug

      // Get the part of the slug we want, ex. journal
      let slugKey = slug.split('/')[1]

      // If the slug matches a template, use that, otherwise
      // fallback to the default journal template.
      // You could use your own logic here.
      let template = templates[slugKey] || templates['journal']

      createPage({
        path: slug, // required
        component: template,
        context: { slug: slug },
      })
    })
  })
}

I’m sure something with how I use promises could be improved, but otherwise this is working well for me, and gives you a decent way to add in more templates.




回答2:


@kennethormandy's answer is correct and will help you add a new blog template!

I just want to add a little bit to it: If you have already organized markdown contents for each template into different directories, it'll feel redundant to add a template props to the frontmatter of every content.

Each MarkdownRemark node has a fileAbsolutePath field, which allows you to filter based on where the content comes from.

For example:

exports.createPages = async ({ actions, graphql }) => {
  const { createPage } = actions
  const results = await graphql(`
    {
       allMarkdownRemark {
         edges {
           node {
             fileAbsolutePath
           }
           // ...other useful fields
         }
       }
    }
  `)

  if (results.errors) throw results.errors
  results.data.allMarkdownRemark.edges.forEach(({ node }) => {
    let template
    if (node.fileAbsolutePath.includes('/blogs/')) template = path.resolve('path/to/blog/template')

    createPage({ ... }) // ...etc
  })
}


来源:https://stackoverflow.com/questions/54637465/how-to-create-a-second-blog-template-to-my-gatsby-site

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!