Ссылка на Codesandbox здесь.
Каждый раз, когда я пытаюсь опубликовать новую запись в блоге с помощью NetlifyCMS, она сообщает, что публикуется. Однако моя сборка Netlify дает сбой и фактически не публикует сообщения в блоге.
Вот ошибка, которую я получаю:
12:44:22 PM: error Your site's "gatsby-node.js" must set the page path when creating a page.
12:44:22 PM: The page object passed to createPage:
12:44:22 PM: {
12:44:22 PM: "path": null,
12:44:22 PM: "component": "/opt/build/repo/src/templates/blogTemplate.js",
12:44:22 PM: "context": {
12:44:22 PM: "slug": null
12:44:22 PM: }
12:44:22 PM: }
12:44:22 PM: See the documentation for the "createPage" action — https://www.gatsbyjs.org/docs/actions/#createPage
12:44:22 PM: not finished createPages - 0.042s
Причина, по которой я получаю эту ошибку, заключается в том, что при публикации новых сообщений в файл уценки нового сообщения в блоге не добавляется автоматически тег «slug». Пример:
---
title: 10 of the best SEO strategies for 2021
slug: /posts/10-best-seo-strategies-2021/ <-- I had to manually add this in the markdown file. This line is completely missing when pushing new blog posts live. This is causing the site build to fail.
date: 2021-03-26T23:53:24.128Z
excerpt: >-
In this post, we go over 10 of the best SEO strategies for 2021. If you want
more business, read more now!
---
Как только я вручную добавляю сообщение в блоге в виде файла уценки за пределами NetlifyCMS, добавляю тег slug и нажимаю на мастер, он успешно строится. Очевидно, я не хочу делать это каждый раз, я хочу, чтобы мой сайт нормально публиковался из NetlifyCMS.
gatsby-node.js:
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions
const blogPostTemplate = require.resolve(`./src/templates/blogTemplate.js`)
const result = await graphql(`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
limit: 1000
) {
edges {
node {
frontmatter {
slug
}
}
}
}
}
`)
// Handle errors
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.slug,
component: blogPostTemplate,
context: {
// additional data can be passed via context
slug: node.frontmatter.slug,
},
})
})
}
GraphQL pageQuery в моем файле /src/pages/posts.js:
export const pageQuery = graphql`
query {
allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
}
}
}
}
}
`
Конфиг.yml:
backend:
name: github
repo: my-repo
media_folder: uploads
public_folder: /uploads
collections:
- name: "posts"
label: "Posts"
folder: "posts"
create: true
slug: "{{slug}}"
fields:
- { label: "Title", name: "title", widget: "string" }
- { label: "Publish Date", name: "date", widget: "date" }
- { label: "Excerpt", name: "excerpt", widget: "string" }
- { label: "Body", name: "body", widget: "markdown" }
blogTemplate.js file:
export const pageQuery = graphql`
query($slug: String!) {
markdownRemark(frontmatter: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
excerpt
}
}
}
`
Любая идея, почему это может происходить?
🤔 А знаете ли вы, что...
Node.js позволяет создавать RESTful API с помощью библиотеки Restify.
Любая идея, почему это может происходить?
Что ж, вы пытаетесь запросить поле slug
, а оно никогда не устанавливалось (по крайней мере, вначале). Ваш frontmatter
имеет следующие поля:
Но не slug
.
Стандартный способ — добавить его в свой config.yml
:
- { name: slug, label: Slug, required: true, widget: string }
Добавив это, ваш запрос будет работать автоматически.
Другой метод — использовать встроенные прослушиватели и преобразователи (API-интерфейсы узлов) от Gatsby для создания slug
на основе ранее установленного параметра, но вам нужно будет изменить свой запрос. В свой gatsby-node.js
добавьте:
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions;
if (node.internal.type === `MarkdownRemark`) {
let value = createFilePath({ node, getNode });
createNodeField({
name: `slug`,
node,
value,
});
}
};
С помощью onCreateNode
вы создаете новый узел на основе некоторых правил (подробнее). Это создаст новую коллекцию для запроса с именем fields
и slug
внутри. Поэтому вам нужно только адаптировать его, например:
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions
const blogPostTemplate = require.resolve(`./src/templates/blogTemplate.js`)
const result = await graphql(`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
limit: 1000
) {
edges {
node {
fields{
slug
}
frontmatter {
slug // not needed now
}
}
}
}
}
`)
// Handle errors
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: blogPostTemplate,
context: {
// additional data can be passed via context
slug: node.frontmatter.slug,
},
})
})
}
Не существует «автоматического» способа добиться этого без погружения в дополнительные схемы Node. Вы только создаете файл уценки и запрашиваете его содержимое. Какова логика создания slug
с нуля? slug
поля всегда должны быть обязательными.
Вы можете попробовать изменить следующее:
createNodeField({
name: `slug`,
node,
value,
});
Чтобы добавить пользовательский value
на основе некоторой логики, если slug
не определен.
Другое дело вне темы. Вы создаете дубликат excerpt
:
Один в вашей уценке (из CMS Netlify):
- { label: "Excerpt", name: "excerpt", widget: "string" }
Один создается автоматически в вашем запросе GraphQL. Файловая система GraphQL + Gatsby добавляет пользовательское поле excerpt
, которое получается в результате разделения содержимого body
с помощью фильтрации pruneLength
вне frontmatter
:
export const pageQuery = graphql`
query {
allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
}
}
}
}
}
`
Я думаю, что вы смешиваете вещи здесь, я бы рекомендовал использовать только один из них, чтобы избежать недоразумений в вашем коде.