如何获取站点地图 Gatsby 的静态文件的更新/lastmod 值

Tri*_*mas 4 reactjs graphql gatsby

我一直在使用 Gatsby 并尝试为静态页面创建一个sitemap带有值的页面 ( )。我看到一个随机代码片段,其中有人在他的代码片段中运行了下面的查询,并且能够获取他上次修改它们的日期。lastmodsrc/pagesgatsby-config.js

allSitePage {
  nodes {
    path
    context {
      updated
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我没能实现同样的壮举。

这是我到目前为止所尝试过的。我假设他使用上下文管理器并在js文件中设置上下文,并在每次编辑文件时手动更新上下文的值。

allSitePage {
  nodes {
    path
    context {
      updated
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我再次运行了查询,但无法传递要在graphql查询中看到的值。这是我在 Graphql 游乐场中运行的查询。

query MyQuery {
  allSitePage {
    nodes {
      id
      context {
        updated
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这就是 Graphql 游乐场中我的整个数据结构的样子。 graphql Playground 的数据结构,特别是 allSitePage

我如何才能获取/设置创建站点地图时updated要使用的值?gatsby-config.js

ngl*_*glk 10

1. 用于gatsby-source-filesystem将静态页面文件添加到文件系统中,以便您可以查询它们。

添加gatsby-config.js以下内容:

{
  resolve: "gatsby-source-filesystem",
  options: {
    name: "pages",
    path: "./src/pages/",
  },
},
Run Code Online (Sandbox Code Playgroud)

注意:您name在此处对属性使用的任何内容都将成为您在查询中过滤的内容。

2. 添加到您的项目中,在最新提交的字段gatsby-transformer-gitinfo上添加一些 git 信息。File插件文档

只需在步骤 1 下声明它,如下所示:

{
  resolve: "gatsby-source-filesystem",
  options: {
    name: "pages",
    path: "./src/pages/",
  },
},
`gatsby-transformer-gitinfo`,
Run Code Online (Sandbox Code Playgroud)

我们使用这个插件是因为Gatsby 节点中的任何 /// 字段在部署modifiedTime时都会被覆盖mtime,因为 git 不记录或保留文件时间戳元数据。changeTimectimeFile

3. 现在我们已将所有必要的数据添加到 GraphQL 中,并且可以查询它以查看其外观:

query MyQuery {
  site {
    siteMetadata {
      siteUrl
    }
  }
  allSitePage {
    nodes {
      path
    }
  }
  allFile(filter: {sourceInstanceName: {eq: "pages"}}) {
    edges {
      node {
        fields {
          gitLogLatestDate
        }
        name
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

注意: sourceInstanceName应等于您在步骤 1 中设置的值options.name

查询结果应如下所示:

{
  "data": {
    "site": {
      "siteMetadata": {
        "siteUrl": "https://www.example.com"
      }
    },
    "allSitePage": {
      "nodes": [
        {
          "path": "/dev-404-page/"
        },
        {
          "path": "/404/"
        },
        {
          "path": "/404.html"
        },
        {
          "path": "/contact/"
        },
        {
          "path": "/features/"
        },
        {
          "path": "/"
        },
        {
          "path": "/privacy/"
        },
        {
          "path": "/terms/"
        }
      ]
    },
    "allFile": {
      "edges": [
        {
          "node": {
            "fields": {
              "gitLogLatestDate": "2021-12-09 23:18:29 -0600"
            },
            "name": "404"
          }
        },
        {
          "node": {
            "fields": {
              "gitLogLatestDate": "2021-12-09 23:18:29 -0600"
            },
            "name": "contact"
          }
        },
        {
          "node": {
            "fields": {
              "gitLogLatestDate": "2021-12-09 23:18:29 -0600"
            },
            "name": "privacy"
          }
        },
        {
          "node": {
            "fields": {
              "gitLogLatestDate": "2021-12-07 19:11:12 -0600"
            },
            "name": "index"
          }
        },
        {
          "node": {
            "fields": {
              "gitLogLatestDate": "2021-12-09 23:18:29 -0600"
            },
            "name": "terms"
          }
        },
        {
          "node": {
            "fields": {
              "gitLogLatestDate": "2021-12-09 23:18:29 -0600"
            },
            "name": "features"
          }
        }
      ]
    }
  },
  "extensions": {}
}
Run Code Online (Sandbox Code Playgroud)

4. 现在让我们把它们放在一起gatsby-config.js

{
  resolve: "gatsby-source-filesystem",
  options: {
    name: "pages",
    path: "./src/pages/",
  },
},
`gatsby-transformer-gitinfo`,
{
  resolve: "gatsby-plugin-sitemap",
  options: {
    query: `{
      site {
        siteMetadata {
          siteUrl
        }
      }
      allSitePage {
        nodes {
          path
        }
      }
      allFile(filter: {sourceInstanceName: {eq: "pages"}}) {
        edges {
          node {
            fields {
              gitLogLatestDate
            }
            name
          }
        }
      }
    }`,
    resolvePages: ({
      allSitePage: { nodes: sitePages },
      allFile: { edges: pageFiles }
    }) => {
      return sitePages.map(page => {
        const pageFile = pageFiles.find(({ node }) => {
          const fileName = node.name === 'index' ? '/' : `/${node.name}/`;
          return page.path === fileName;
        });

        return { ...page, ...pageFile?.node?.fields }
      })
    },
    serialize: ({ path, gitLogLatestDate }) => {
      return {
        url: path,
        lastmod: gitLogLatestDate
      }
    },
    createLinkInHead: true,
  },
}
Run Code Online (Sandbox Code Playgroud)

选项说明gatsby-plugin-sitemap

  • query是不言自明的

  • resolvePages

    • 接受来自 的结果,因此我们可以使用解构将和节点/边query分配给变量。allSitePageallFile
    • 通过sitePages( allSitePage.nodes) 进行映射,使用 来page.path查找匹配的文件name
      • 如果文件name用于匹配,因为路径不是,index否则只需将文件包装在分隔符中。//index/name
    • 返回合并后的页面对象和包含 git 信息的匹配文件对象
    • (生成的对象数组resolvePages成为allPages插件代码中的对象)
  • serialize

    • 该函数映射来自allPages的页面对象数组resolvePages,因此我们可以再次使用解构来获取每个页面的pathgitLogLatestDate
    • 返回属性:
      • url:插件将使用siteMetaData.siteUrl查询中的内容并附加此处分配的任何值来生成完整的 URL。

      • lastmod:需要有效的时间值,并且无论传入的格式如何,始终输出完整的 ISO8601 字符串。

        注意:目前似乎没有办法lastmod只能通过gatsby-plugin-sitemap. 这是因为在幕后gatsby-plugin-sitemap使用此站点地lastmodDateOnly图库,虽然该库的某些组件有一个会截断时间字符串的标志,gatsby-plugin-sitemap但不使用它们。

  • createLinkInHead:链接站点头部的站点地图索引

5. 最后,运行gatsby build,您应该看到结果显示在public/sitemap/sitemap-0.xml

(似乎gatsby-plugin-sitemap最近切换到了这个位置,所以如果您使用的是旧版本的插件,则可能在其他地方。)

结果应该是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
        xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
    <url>
        <loc>https://www.example.com/contact/</loc>
        <lastmod>2021-12-10T05:18:29.000Z</lastmod>
    </url>
    <url>
        <loc>https://www.example.com/features/</loc>
        <lastmod>2021-12-10T05:18:29.000Z</lastmod>
    </url>
    <url>
        <loc>https://www.example.com/</loc>
        <lastmod>2021-12-08T01:11:12.000Z</lastmod>
    </url>
    <url>
        <loc>https://www.example.com/privacy/</loc>
        <lastmod>2021-12-10T05:18:29.000Z</lastmod>
    </url>
    <url>
        <loc>https://www.example.com/terms/</loc>
        <lastmod>2021-12-10T05:18:29.000Z</lastmod>
    </url>
</urlset>
Run Code Online (Sandbox Code Playgroud)

额外的、可能有用的细节 - 我正在使用的所有内容的版本:

"gatsby": "^4.0.0",
"gatsby-plugin-sitemap": "^5.3.0",
"gatsby-source-filesystem": "^4.3.0",
"gatsby-transformer-gitinfo": "^1.1.0",
Run Code Online (Sandbox Code Playgroud)