如何在 NetlifyCMS 构建中修复“TypeError:childImageSharp 未定义”?

Posted

技术标签:

【中文标题】如何在 NetlifyCMS 构建中修复“TypeError:childImageSharp 未定义”?【英文标题】:How do I fix "TypeError: childImageSharp is undefined" on NetlifyCMS build? 【发布时间】:2021-02-16 14:26:50 【问题描述】:

我正在现有的 gatsby 网站上设置一个简单的博客页面,我希望使用 netlify cms 的人能够为博客文章上传缩略图。我已经设法这样做并使用 graphigl 找到它

现在我想将它设置到我的博客文章页面:

import React from "react"
import  Link, graphql, useStaticQuery  from "gatsby"

import Layout from "../components/layout/layout"

const Blog = () => 
  const data = useStaticQuery(graphql`
    query 
      allMarkdownRemark 
        edges 
          node 
            frontmatter 
              title
              date
              thumbnail 
                childImageSharp 
                  fluid(maxWidth: 400) 
                    src
                  
                
              
            
            fields 
              slug
            
          
        
      
    
  `)

  return (
    <>
      <Layout>
        <main className="main">
          <div className="articles">
            <h1 className="articles__title">Articles</h1>
            data.allMarkdownRemark.edges.map(edge => 
              return (
                <section className="articles__list">
                  <a className="articles__article">
                    <div className="articles__article-artwork">
                      <figure className="articles__article-artwork-wrapper">
                        edge.node.frontmatter.thumbnail.childSharpImage.fluid.src
                      </figure>
                    </div>
                    <h2 className="articles__article-title">
                      <Link to=`/blog/$edge.node.fields.slug`>
                        edge.node.frontmatter.title
                      </Link>
                    </h2>
                    <Link>
                      <p>edge.node.frontmatter.date</p>
                    </Link>
                    <div className="articles__article-description">
                      <p></p>
                    </div>
                    <span className="articles__article-more">Read more...</span>
                  </a>
                </section>
              )
            )
          </div>
        </main>
      </Layout>
    </>
  )

export default Blog

然后在 netlify 上重新部署时出现这些错误。

config.yml

backend:
  name: github
  branch: development
  repo: (removed for work reasons)

media_folder: static/img
public_folder: img

collections:
  - name: "blog"
    label: "Blog"
    folder: "src/posts"
    create: true
    slug: "slug"
    fields:
      - label: "Layout", name: "layout", widget: "hidden", default: "blog"
      - label: "Title", name: "title", widget: "string"
      - label: "Publish Date", name: "date", widget: "datetime"
      - label: "Body", name: "body", widget: "markdown"
      - label: "Image", name: "thumbnail", widget: "image"

gatsby-node.js

const path = require('path')

module.exports.onCreateNode = ( node, actions ) => 
    const  createNodeField  = actions

    if (node.internal.type === "MarkdownRemark") 
        const slug = path.basename(node.fileAbsolutePath, '.md')

        createNodeField(
            node,
            name: 'slug',
            value: slug
        )
    


module.exports.createPages = async ( graphql, actions) => 
    const  createPage  = actions
    const blogTemplate = path.resolve('./src/templates/blog.js')
    const res = await graphql(`
        query 
            allMarkdownRemark 
                edges 
                    node 
                        fields 
                            slug
                        
                    
                
            
        
    `)

    res.data.allMarkdownRemark.edges.forEach((edge) => 
        createPage(
            component: blogTemplate,
            path: `/blog/$edge.node.fields.slug`,
            context: 
                slug: edge.node.fields.slug
            
        )
    )

gatsby-config.js

module.exports = 
  siteMetadata: 
    title: `removed for work reasons`,
    description: `removed`,
    author: `removed`,
  ,
  plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-sass`,
    `gatsby-plugin-remove-serviceworker`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `images`,
        path: `$__dirname/src/images`,
      ,
    ,
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `img`,
        path: `$__dirname/static/img`,
      ,
    ,
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `src`,
        path: `$__dirname/src`,
      ,
    ,
    
      resolve: `gatsby-plugin-manifest`,
      options: 
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
      ,
    ,
    
      resolve: 'gatsby-plugin-react-svg',
      options: 
        rule: 
          include: /assets/
        
      
    ,
    
      resolve: `gatsby-transformer-remark`,
      options: 
        plugins: [
          
            resolve: `gatsby-remark-images`,
              options: 
                maxWidth: 590,
              
          ,
          
            resolve: `gatsby-plugin-netlify-cms-paths`,
            options: 
              cmsConfig: `/static/admin/config.yml`
            
          
        ]
      
    ,
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
    `gatsby-plugin-netlify-cms`,
    `gatsby-plugin-netlify`,
  ],


我真的认为使用 netlify cms 将博客页面添加到我现有的 gatsby 网站会轻而易举,但这是我尝试过的最困难的事情之一。

非常感谢任何帮助。

谢谢

【问题讨论】:

【参考方案1】:

我觉得有些奇怪。

您的查询不起作用(因此,破坏了代码),因为它找不到您的图像。将您的 config.yml 媒体路径更改为:

  media_folder: static/img
  public_folder: /img

注意public_folder 路径中的斜杠 (/)。

这是因为它是相对路径,必须以斜杠开头。 From Netlify docs(斜线部分加粗):

公共文件夹

此设置是必需的。

public_folder 选项指定文件所在的文件夹路径 由媒体库上传的将被访问,相对于基础 的建成网站。对于由 [file] 或 [image] 小部件控制的字段, 该字段的值是通过将此路径添加到 所选文件的文件名。默认为 media_folder 的值, 如果还没有包含一个开头/

   public_folder: "/images/uploads"

根据上述设置,如果用户使用了图像小部件字段 调用avatar 上传并选择名为philosoraptor.png 的图像, 图像将保存到存储库中 /static/img/philosoraptor.png,以及头像字段 文件将设置为/img/philosoraptor.png

您的media_folder 看起来不错。

您在&lt;figure&gt; 标记内渲染图像的方式。按照您的方法,它将呈现一个带有图像路径的字符串,但是,您正在使用来自gatsby-image 的锐利,但您没有使用它。在一些试验中,我建议以下:

<figure>
   <Img fluid=edges.node.frontmatter.thumbnail.childImageSharp.fluid>
</figure>

按照gatsby-image 方法,您还应该使用如下查询片段:

   const data = useStaticQuery(graphql`
  query 
    allMarkdownRemark 
      edges 
        node 
          frontmatter 
            title
            date
            thumbnail 
              childImageSharp 
                fluid(maxWidth: 400) 
                  ...GatsbyImageSharpFluid
                
              
            
          
          fields 
            slug
          
        
      
    
  
`)

注意...GatsbyImageSharpFluid 片段以获取所有需要的数据以使用gatsby-image

您正在使用staticQuery,但您不需要它,因为您的所有数据都来自 CMS。您应该使用page/template query 来提高性能,但这会改变您的页面结构。

在 Gatsby 中创建动态页面的“标准”方式是使用gatsby-node.js 来使用createPage API,将所需数据传递给模板(通常是idslug)并使用该唯一数据检索博客/帖子信息。

您正在通过上下文传递slug,但您从未使用它:

  context: 
    slug: edge.node.fields.slug
  

此外,您再次使用静态查询 (allMarkdownRemark) 循环浏览所有文章,这没有意义,而且浪费时间和性能。

您的Blog 模板应如下所示:

  import React from 'react'
  import  graphql  from 'gatsby'

  const Blog = (data) => 
    return (
      <div>
       Blog title is: data.markdownRemark.frontmatter.title
     </div>
   )


export const query = graphql`
   query BlogQuery($slug: String!) 
  query 
    markdownRemark(fields:  slug:  eq: $slug ) 
          html
          frontmatter 
            title
            date
            thumbnail 
              childImageSharp 
                fluid(maxWidth: 400) 
                  ...GatsbyImageSharpFluid
                
              
            
          
          fields 
            slug
          
        
     
   
`

export default Blog

请注意,您将 slug ($slug) 作为必需参数 (String!) 传递,因此页面查询不能为 null。之后,您将过滤降价节点 (markdownRemark) 以获取与您在 gatsby-node.js 文件中传递的上下文相匹配的节点。换句话说,在这种情况下,您拥有每个帖子的数据。

另外请注意,您可能需要更改查询以匹配您的数据结构,我是在不知道您的字段的情况下从头开始发布的。使用localhost:8000/___graphql(GraphQL 操场)来检查它。您的 Fragment 无法在其中工作,因为它是 GraphQL 的限制,但它可以在您的代码上工作,因此请避免在其中使用它,但将其保留在您的代码中。

【讨论】:

谢谢伙计。所以这个页面是我的博客文章页面,我为实际的单个帖子制作了一个模板页面,我没有使用 staticQuery 而是只使用查询和 slug ,这是应该通过的地方。我做了一些更改,但我仍然无法让 childImageSharp 工作。现在我得到“无法在“文件”类型上查询字段“childSharpImage””。这太令人困惑了! 抱歉改成 childImageSharp。修正了错字,现在我回到“TypeError:无法读取未定义的属性'childImageSharp'” 实际上,我能够让图像在我的个人博客模板上工作,但在上面的博客文章页面上没有运气。仍然错误 TypeError: Cannot read property 'childImageSharp' of null

以上是关于如何在 NetlifyCMS 构建中修复“TypeError:childImageSharp 未定义”?的主要内容,如果未能解决你的问题,请参考以下文章

升级到 NextJS 9.0 后如何修复 React Hooks?

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

Gatsby 警告构建“查询时间过长”

如何修复以下 Django 错误:“类型:IOError”“值:[Errno 13] 权限被拒绝”

Gatsby 和 Netlify CMS 预览错误与渲染 StaticQuery

如何修复 Android 中偏移 YYY 处的 Unmarshalling unknown type code XXX?