如何使用 NetlifyCMS 和 Gatsby 在降价文件中自动添加 'slug' 标签?
How to add 'slug' tag automatically in markdown files using NetlifyCMS and Gatsby?
Codesandbox link here.
每当我尝试使用 NetlifyCMS 发布新博客 post 时,它都会显示已发布。然而,我的 Netlify 构建失败并且实际上没有推送任何博客 posts live。
这是我得到的错误:
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
之所以出现这个错误是因为当发布新的posts时,新博客post的markdown文件不会自动添加'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!
---
一旦我手动将博客 post 添加为 NetlifyCMS 之外的降价文件,并添加 slug 标签并推送到 master,它就成功构建了。显然我不想每次都这样做,我希望我的网站能够从 NetlifyCMS 正常发布。
盖茨比-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,
},
})
})
}
我的 /src/pages/posts.js 文件中的 GraphQL pageQuery:
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
}
}
}
}
}
`
Config.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
}
}
}
`
知道为什么会这样吗?
Any idea why this may be happening?
好吧,您正在尝试查询 slug
字段,但它从未被设置(至少在开始时)。您的 frontmatter
具有以下字段:
- 标题
- 发布
- 节选
- Body
但不是slug
。
标准方法是将其添加到您的 config.yml
:
- { name: slug, label: Slug, required: true, widget: string }
添加这个,您的查询将自动运行。
另一种方法是使用 Gatsby 中的 built-in listeners and the resolvers (Node APIs) 根据先前设置的参数生成 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
,您将根据某些规则 (more details) 创建一个新节点。这将创建一个新的 collection 来查询,名为 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,
});
如果 slug
未定义,则根据某些逻辑添加自定义 value
。
题外话。您正在创建重复的 excerpt
:
你的 markdown 中的一个(来自 Netlify 的 CMS):
- { label: "Excerpt", name: "excerpt", widget: "string" }
在您的 GraphQL 查询中自动创建一个。 GraphQL + Gatsby 文件系统添加了一个自定义 excerpt
字段,该字段是通过在 frontmatter
:
之外使用 pruneLength
过滤对 body
的内容进行拆分而产生的
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
}
}
}
}
}
`
我认为您在这里混用了一些东西,我建议您只使用其中一种以避免代码中的误解。
Codesandbox link here.
每当我尝试使用 NetlifyCMS 发布新博客 post 时,它都会显示已发布。然而,我的 Netlify 构建失败并且实际上没有推送任何博客 posts live。
这是我得到的错误:
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
之所以出现这个错误是因为当发布新的posts时,新博客post的markdown文件不会自动添加'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!
---
一旦我手动将博客 post 添加为 NetlifyCMS 之外的降价文件,并添加 slug 标签并推送到 master,它就成功构建了。显然我不想每次都这样做,我希望我的网站能够从 NetlifyCMS 正常发布。
盖茨比-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,
},
})
})
}
我的 /src/pages/posts.js 文件中的 GraphQL pageQuery:
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
}
}
}
}
}
`
Config.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
}
}
}
`
知道为什么会这样吗?
Any idea why this may be happening?
好吧,您正在尝试查询 slug
字段,但它从未被设置(至少在开始时)。您的 frontmatter
具有以下字段:
- 标题
- 发布
- 节选
- Body
但不是slug
。
标准方法是将其添加到您的 config.yml
:
- { name: slug, label: Slug, required: true, widget: string }
添加这个,您的查询将自动运行。
另一种方法是使用 Gatsby 中的 built-in listeners and the resolvers (Node APIs) 根据先前设置的参数生成 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
,您将根据某些规则 (more details) 创建一个新节点。这将创建一个新的 collection 来查询,名为 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,
});
如果 slug
未定义,则根据某些逻辑添加自定义 value
。
题外话。您正在创建重复的 excerpt
:
你的 markdown 中的一个(来自 Netlify 的 CMS):
- { label: "Excerpt", name: "excerpt", widget: "string" }
在您的 GraphQL 查询中自动创建一个。 GraphQL + Gatsby 文件系统添加了一个自定义
之外使用excerpt
字段,该字段是通过在frontmatter
:pruneLength
过滤对body
的内容进行拆分而产生的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 } } } } } `
我认为您在这里混用了一些东西,我建议您只使用其中一种以避免代码中的误解。