How do I fix "TypeError: childImageSharp is undefined" on NetlifyCMS build?
How do I fix "TypeError: childImageSharp is undefined" on NetlifyCMS build?
我正在现有的 gatsby 网站上设置一个简单的博客页面,我希望使用 netlify cms 的人能够上传博客的缩略图 post。我设法做到了,并使用 graphigl
找到了它
现在我想把它设置到我的博客post页面:
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"}
盖茨比-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
}
})
})
}
盖茨比-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 站点会轻而易举,但这是我尝试过的最困难的事情之一。
非常感谢任何帮助。
谢谢
有几件事对我来说很奇怪。
您的查询无效(因此,破坏了代码),因为它找不到您的图像。将您的 config.yml
媒体路径更改为:
media_folder: static/img
public_folder: /img
注意 public_folder
路径中的斜杠 (/
)。
这是因为它是相对路径并且必须以斜杠开头。 From Netlify docs(斜线部分加粗):
Public Folder
This setting is required.
The public_folder
option specifies the folder path where the files
uploaded by the media library will be accessed, relative to the base
of the built site. For fields controlled by [file] or [image] widgets,
the value of the field is generated by prepending this path to the
filename of the selected file. Defaults to the value of media_folder,
with an opening /
if one is not already included.
public_folder: "/images/uploads"
Based on the settings above, if a user used an image widget field
called avatar
to upload and select an image called philosoraptor.png
,
the image would be saved to the repository at
/static/img/philosoraptor.png
, and the avatar field for the
file would be set to /img/philosoraptor.png
.
你的 media_folder
看起来不错。
您在 <figure>
标签内呈现图像的方式。按照您的方法,它将呈现一个带有图像路径的字符串,但是,您使用的是 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,将需要的数据传递给模板(通常是 id
或 slug
) 并使用该唯一数据检索 blog/post 信息。
您正在通过上下文传递 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!
) 传递,因此它不能为页面查询的空值。之后,您过滤降价节点 (markdownRemark
) 以获得与您在 gatsby-node.js
文件中传递的上下文相匹配的节点。换句话说,在这种情况下,您拥有每个 post.
的数据
另请注意,您可能需要更改查询以匹配您的数据结构,我 post 在不知道您的字段的情况下从头开始编辑它。使用 localhost:8000/___graphql
(GraphQL 操场)来检查它。你的片段不会在那里工作,因为它是 GraphQL 的限制,但它会在你的代码上工作,所以避免在那里使用它,但将它保留在你的代码中。
我正在现有的 gatsby 网站上设置一个简单的博客页面,我希望使用 netlify cms 的人能够上传博客的缩略图 post。我设法做到了,并使用 graphigl
找到了它现在我想把它设置到我的博客post页面:
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"}
盖茨比-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
}
})
})
}
盖茨比-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 站点会轻而易举,但这是我尝试过的最困难的事情之一。
非常感谢任何帮助。
谢谢
有几件事对我来说很奇怪。
您的查询无效(因此,破坏了代码),因为它找不到您的图像。将您的
config.yml
媒体路径更改为:media_folder: static/img public_folder: /img
注意
public_folder
路径中的斜杠 (/
)。这是因为它是相对路径并且必须以斜杠开头。 From Netlify docs(斜线部分加粗):
Public Folder
This setting is required.
The
public_folder
option specifies the folder path where the files uploaded by the media library will be accessed, relative to the base of the built site. For fields controlled by [file] or [image] widgets, the value of the field is generated by prepending this path to the filename of the selected file. Defaults to the value of media_folder, with an opening/
if one is not already included.public_folder: "/images/uploads"
Based on the settings above, if a user used an image widget field called
avatar
to upload and select an image calledphilosoraptor.png
, the image would be saved to the repository at/static/img/philosoraptor.png
, and the avatar field for the file would be set to/img/philosoraptor.png
.
你的 media_folder
看起来不错。
您在
<figure>
标签内呈现图像的方式。按照您的方法,它将呈现一个带有图像路径的字符串,但是,您使用的是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,将需要的数据传递给模板(通常是id
或slug
) 并使用该唯一数据检索 blog/post 信息。您正在通过上下文传递
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!
) 传递,因此它不能为页面查询的空值。之后,您过滤降价节点 (markdownRemark
) 以获得与您在gatsby-node.js
文件中传递的上下文相匹配的节点。换句话说,在这种情况下,您拥有每个 post.另请注意,您可能需要更改查询以匹配您的数据结构,我 post 在不知道您的字段的情况下从头开始编辑它。使用
localhost:8000/___graphql
(GraphQL 操场)来检查它。你的片段不会在那里工作,因为它是 GraphQL 的限制,但它会在你的代码上工作,所以避免在那里使用它,但将它保留在你的代码中。