如何获取站点地图 Gatsby 静态文件的更新/lastmod 值
How to get updated / lastmod value for static files for sitemap Gatsby
我一直在使用 Gatsby,并一直在尝试为静态页面 (src/pages
) 创建一个具有 lastmod
值的 sitemap
。我看到一个 运行dom 代码片段,其中有人 运行 在他的 gatsby-config.js
中查询下面的内容,并且能够得到他最后修改它们的日期。
allSitePage {
nodes {
path
context {
updated
}
}
}
我没能达到同样的成就。
这是我目前尝试过的方法。我假设他正在使用上下文管理器并在他的 js
文件中设置上下文,并在每次他编辑文件时手动更新上下文的值。
const Updated = React.createContext('2021-11-29')
class IndexPage extends React.Component {
render() {
return (
<div>
{/* Example */}
</div>
)
}
}
/* Also tried IndexPage.contextType = Updated */
IndexPage.useContext = Updated
export default IndexPage
我再次 运行 查询,但无法传递要在 graphql
查询中看到的值。这是我 运行 在 Graphql 操场上的查询。
query MyQuery {
allSitePage {
nodes {
id
context {
updated
}
}
}
}
这就是我在 Graphql 游乐场中的整个数据结构。
创建站点地图时如何获取/设置要在 gatsby-config.js
中使用的 updated
值?
1.使用 gatsby-source-filesystem
将静态页面文件添加到您的文件系统,以便您可以查询它们。
在gatsby-config.js
中添加以下内容:
{
resolve: "gatsby-source-filesystem",
options: {
name: "pages",
path: "./src/pages/",
},
},
注意:您在name
属性中使用的任何内容都将成为您在查询中过滤的内容。
2。将 gatsby-transformer-gitinfo
添加到您的项目以在最新提交的 File
字段上添加一些 git 信息。 (plugin docs)
只需在步骤 1 下声明它,如下所示:
{
resolve: "gatsby-source-filesystem",
options: {
name: "pages",
path: "./src/pages/",
},
},
`gatsby-transformer-gitinfo`,
我们使用这个插件是因为 Gatsby 的 File
节点中的任何 modifiedTime
/mtime
/changeTime
/ctime
字段在部署时被覆盖因为 git 不记录或保留文件时间戳元数据。
3。现在我们已经将所有必要的数据添加到 GraphQL 中,并且可以查询它以查看它的外观:
query MyQuery {
site {
siteMetadata {
siteUrl
}
}
allSitePage {
nodes {
path
}
}
allFile(filter: {sourceInstanceName: {eq: "pages"}}) {
edges {
node {
fields {
gitLogLatestDate
}
name
}
}
}
}
注意: 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": {}
}
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,
},
}
gatsby-plugin-sitemap
选项的解释:
query
不言自明
resolvePages
- 接受
query
的结果,所以我们可以使用解构将allSitePage
和allFile
nodes/edges分配给变量。
- 通过
sitePages
映射(allSitePage.nodes
),使用page.path
找到匹配文件name
。
- 如果文件
name
是 index
使用 /
进行匹配,因为路径不是 /index/
,否则只需将文件 name
包装在分隔符中.
- return 包含 git 信息的合并页面对象和匹配文件对象
- (从
resolvePages
生成的对象数组成为插件代码中的 allPages
对象)
serialize
- 这个函数映射到
allPages
,也就是来自 resolvePages
的页面对象数组,因此我们可以再次使用解构来获取每个页面的 path
和 gitLogLatestDate
。
- Return 属性:
url
:插件将使用查询中的 siteMetaData.siteUrl
并附加此处分配的任何值以生成完整的 URL.
lastmod
:需要一个有效的时间值,并且无论传入的格式如何,总是输出一个完整的 ISO8601 字符串。
注意:目前似乎没有办法只通过gatsby-plugin-sitemap
将lastmod
格式化为日期。这是因为 gatsby-plugin-sitemap
在幕后使用了这个 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>
额外的,可能有用的细节 - 我正在使用的所有版本:
"gatsby": "^4.0.0",
"gatsby-plugin-sitemap": "^5.3.0",
"gatsby-source-filesystem": "^4.3.0",
"gatsby-transformer-gitinfo": "^1.1.0",
"allSitePage": {
"nodes": [
{
"path": "/signup/united-states/new-york/"
},
{
"path": "/signup/united-kingdom/london/"
}
]
}
如果您的项目有嵌套页面结构,请使用下面的代码。
{
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
}
relativePath
}
}
}
}`,
resolvePages: ({
allSitePage: {
nodes: sitePages
},
allFile: {
edges: pageFiles
}
}) => {
return sitePages.map(page => {
const pageFile = pageFiles.find(({
node
}) => {
let fileName = node.relativePath.split('.').slice(0, -1).join('.')
fileName = fileName === 'index' ? '/' : `/${fileName.replace('/index','')}/`
return page.path === fileName;
});
return { ...page, ...pageFile?.node?.fields }
})
},
serialize: ({
path,
gitLogLatestDate
}) => {
return {
url: path,
lastmod: gitLogLatestDate
}
},
createLinkInHead: true,
},
}
我一直在使用 Gatsby,并一直在尝试为静态页面 (src/pages
) 创建一个具有 lastmod
值的 sitemap
。我看到一个 运行dom 代码片段,其中有人 运行 在他的 gatsby-config.js
中查询下面的内容,并且能够得到他最后修改它们的日期。
allSitePage {
nodes {
path
context {
updated
}
}
}
我没能达到同样的成就。
这是我目前尝试过的方法。我假设他正在使用上下文管理器并在他的 js
文件中设置上下文,并在每次他编辑文件时手动更新上下文的值。
const Updated = React.createContext('2021-11-29')
class IndexPage extends React.Component {
render() {
return (
<div>
{/* Example */}
</div>
)
}
}
/* Also tried IndexPage.contextType = Updated */
IndexPage.useContext = Updated
export default IndexPage
我再次 运行 查询,但无法传递要在 graphql
查询中看到的值。这是我 运行 在 Graphql 操场上的查询。
query MyQuery {
allSitePage {
nodes {
id
context {
updated
}
}
}
}
这就是我在 Graphql 游乐场中的整个数据结构。
创建站点地图时如何获取/设置要在 gatsby-config.js
中使用的 updated
值?
1.使用 gatsby-source-filesystem
将静态页面文件添加到您的文件系统,以便您可以查询它们。
在gatsby-config.js
中添加以下内容:
{
resolve: "gatsby-source-filesystem",
options: {
name: "pages",
path: "./src/pages/",
},
},
注意:您在name
属性中使用的任何内容都将成为您在查询中过滤的内容。
2。将 gatsby-transformer-gitinfo
添加到您的项目以在最新提交的 File
字段上添加一些 git 信息。 (plugin docs)
只需在步骤 1 下声明它,如下所示:
{
resolve: "gatsby-source-filesystem",
options: {
name: "pages",
path: "./src/pages/",
},
},
`gatsby-transformer-gitinfo`,
我们使用这个插件是因为 Gatsby 的 File
节点中的任何 modifiedTime
/mtime
/changeTime
/ctime
字段在部署时被覆盖因为 git 不记录或保留文件时间戳元数据。
3。现在我们已经将所有必要的数据添加到 GraphQL 中,并且可以查询它以查看它的外观:
query MyQuery {
site {
siteMetadata {
siteUrl
}
}
allSitePage {
nodes {
path
}
}
allFile(filter: {sourceInstanceName: {eq: "pages"}}) {
edges {
node {
fields {
gitLogLatestDate
}
name
}
}
}
}
注意: 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": {}
}
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,
},
}
gatsby-plugin-sitemap
选项的解释:
query
不言自明resolvePages
- 接受
query
的结果,所以我们可以使用解构将allSitePage
和allFile
nodes/edges分配给变量。 - 通过
sitePages
映射(allSitePage.nodes
),使用page.path
找到匹配文件name
。- 如果文件
name
是index
使用/
进行匹配,因为路径不是/index/
,否则只需将文件name
包装在分隔符中.
- 如果文件
- return 包含 git 信息的合并页面对象和匹配文件对象
- (从
resolvePages
生成的对象数组成为插件代码中的allPages
对象)
- 接受
serialize
- 这个函数映射到
allPages
,也就是来自resolvePages
的页面对象数组,因此我们可以再次使用解构来获取每个页面的path
和gitLogLatestDate
。 - Return 属性:
url
:插件将使用查询中的siteMetaData.siteUrl
并附加此处分配的任何值以生成完整的 URL.lastmod
:需要一个有效的时间值,并且无论传入的格式如何,总是输出一个完整的 ISO8601 字符串。注意:目前似乎没有办法只通过
gatsby-plugin-sitemap
将lastmod
格式化为日期。这是因为gatsby-plugin-sitemap
在幕后使用了这个 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>
额外的,可能有用的细节 - 我正在使用的所有版本:
"gatsby": "^4.0.0",
"gatsby-plugin-sitemap": "^5.3.0",
"gatsby-source-filesystem": "^4.3.0",
"gatsby-transformer-gitinfo": "^1.1.0",
"allSitePage": {
"nodes": [
{
"path": "/signup/united-states/new-york/"
},
{
"path": "/signup/united-kingdom/london/"
}
]
}
如果您的项目有嵌套页面结构,请使用下面的代码。
{
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
}
relativePath
}
}
}
}`,
resolvePages: ({
allSitePage: {
nodes: sitePages
},
allFile: {
edges: pageFiles
}
}) => {
return sitePages.map(page => {
const pageFile = pageFiles.find(({
node
}) => {
let fileName = node.relativePath.split('.').slice(0, -1).join('.')
fileName = fileName === 'index' ? '/' : `/${fileName.replace('/index','')}/`
return page.path === fileName;
});
return { ...page, ...pageFile?.node?.fields }
})
},
serialize: ({
path,
gitLogLatestDate
}) => {
return {
url: path,
lastmod: gitLogLatestDate
}
},
createLinkInHead: true,
},
}