如何为我的 Gatsby 网站创建第二个博客模板

Posted

技术标签:

【中文标题】如何为我的 Gatsby 网站创建第二个博客模板【英文标题】:How to create a second blog template to my Gatsby Site 【发布时间】:2019-07-05 08:31:19 【问题描述】:

我的 Gatsby 网站需要 2 个博客模板:

    故事模板.js products.template.js

我为我的故事运行了故事模板,但我不确定如何调整和更改 gatsby-node + products.template.js 中的现有代码,以便为我的产品制作第二个(不同的)模板。

我已经尝试了所有解决方案和过去的问题,但没有运气。

我在 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,
        )
    )
)

我在 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
        
    

`

这可行,但现在我想在 products-template.js 中为产品创建不同的模板。现在我的产品模板基本上只是从我的故事模板中复制和粘贴的。

我这辈子都想不通。

【问题讨论】:

欢迎来到 SO!这涉及几个步骤(创建新模板、设置新内容、进行新查询、创建新页面),您在哪些步骤遇到问题?您尝试了什么,遇到了什么错误? 【参考方案1】:

就像提到的第一条评论一样,这里可能需要更多的上下文,但我会试一试。我认为问题在于无论页面如何,您都在告诉createPage 函数使用postTemplate 模板组件。

Gatsby 不会自动读取模板目录中的模板或类似的东西,你需要自己添加这个逻辑。

首先,您需要使用其他模板,例如:

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

然后,您需要在这里决定何时使用productsTemplate 而不是postTemplate

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

例如,可能在每个 Markdown 文件中,您都有 template YAML frontmatter:

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

以下是我在自己的网站上尝试以更通用的方式处理它的方法。 URL 结构决定了模板:如果它在/journal,它会得到 Journal 模板组件。如果在/shop,则获取 Shop 模板组件。

这可能不足以进入您现有的网站,但希望它能让您更接近:

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

我确信可以改进我使用 Promise 的方式,但除此之外这对我来说效果很好,并为您提供了一种添加更多模板的好方法。

【讨论】:

【参考方案2】:

@kennethormandy 的回答是正确的,将帮助您添加新的博客模板!

我只是想补充一点:如果您已经将每个模板的 markdown 内容组织到不同的目录中,那么在每个内容的 frontmatter 中添加一个 template 道具会感觉多余。

每个 MarkdownRemark 节点都有一个 fileAbsolutePath 字段,允许您根据内容的来源进行过滤。

例如:

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
  )

【讨论】:

以上是关于如何为我的 Gatsby 网站创建第二个博客模板的主要内容,如果未能解决你的问题,请参考以下文章

正确地将第二个动态模板添加到 Gatsby/NetlifyCMS - 我哪里出错了?

无法在 allMarkdownRemark graphql 上查询字段

如何为 Gatsby 页面查询创建自定义解析器?

如何为 djangocms-blog 设置自定义模板?

如何为我的自定义博客帖子创建档案?

如何为我的 HttpClient PostAsync 第二个参数设置 HttpContent?