React SPA 中某些页面的动态元描述
Dynamic meta descriptions for certain pages in React SPA
我用 React 构建了一个博客,它从 api 中动态获取每个博客条目的数据。
该页面的内容显然根据路线看起来有所不同,例如mysite.com/blog/1
、mysite.com/blog/2
、...
我想要实现的是根据 url 从 api 获取的数据动态更改元描述。特别是 og:title
、og:description
和 og:image
。这样的事情甚至可能吗?
我阅读了有关 SSR/Next.JS 或 Gatsby 的信息,但我不确定如果从 api 调用接收到数据,这是否有效。
我知道 SSR 会在服务器上呈现内容,因此它允许 Google 抓取页面,但不会排除 api 调用吗?
我也明白 Gatsby 构建静态站点,但对我来说这行不通,因为 api 调用是动态的,不能构建到静态站点中。
我非常感谢能给我指明正确方向的提示。
I understand that SSR would render the content on the server, hence it
allows Google to crawl the pages but wouldn't that exclude api calls?
I also understand that Gatsby builds static sites but for me that
wouldn't work because the api calls are dynamic and cannot be built
into a static site.
我认为您误解了 Gatsby 的工作原理。
总而言之,Gatsby 从动态数据(API 调用)生成静态页面,因此,当您 运行 gatsby develop
或 gatsby build
命令时,Gatsby 会获取数据来自来源(在本例中来自您的 API)并生成动态页面(mysite.com/blog/1
、mysite.com/blog/2
等)。
此数据是静态的,这意味着这些来源的每次更改都会迫使您重新获取数据以显示更改(在生产中意味着新的部署)但是,一旦您的页面是静态构建的,您可以即时构建您的 SEO 数据。
这是他们以前在旧网站上使用的旧 Gatsby 工作流程,但我发现它非常不言自明:
在构建时,您的站点是静态生成的,因此您可以使用自定义 SEO 组件或您想要的任何内容完全自定义您的 SEO 要求。大多数启动器都带有一个可以使用的 SEO
组件:
function Seo({ description, lang, meta, title }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
const defaultTitle = site.siteMetadata?.title
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={defaultTitle ? `%s | ${defaultTitle}` : null}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata?.author || ``,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
].concat(meta)}
/>
)
}
由于该组件将 description
、lang
、meta
和 title
分别作为 props
,您可以将其添加到您的博客模板中获取将静态构建的动态数据,这意味着,当部署您的站点时,该数据已经构建,因此 Google 爬虫将立即获取它。
const YourBlogPostTemplate = ({ data }) =>{
return <article>
<SEO title={data.allAPIData.frontmatter.title} />
<h1>I'm the title: {data.allAPIData.frontmatter.title}</h1>
</article>
}
注意:我不会完全自定义它以避免扩展答案,但请理解。
SEO
组件将在构建时使用 title
和其余字段。
您的 API 调用是在页面构建之前获取的,因此,在构建页面时,您的数据已经是静态的。
有一篇非常好的文章 here 描述了如何以最简单的方式解决此问题。
基本上,我需要在我当前的 React 应用程序之上放置一个简单的 NodeJS 服务器。服务器现在提供构建目录中的文件。对于某些路由,我只是将 __PAGE_META__
占位符替换为 Google、Facebook、Twitter 等
所需的元标记
这里用一张简单的图片来描述流程:
以及 NodeJS 部分的简单代码片段:
const path = require("path")
const express = require("express")
const app = express()
const fs = require("fs")
//
const pathToIndex = path.join(__dirname, "build/index.html")
app.get("/", (req, res) => {
const raw = fs.readFileSync(pathToIndex)
const pageTitle = "Homepage - Welcome to my page"
const updated = raw.replace("__PAGE_META__", `<title>${pageTitle}</title>`)
res.send(updated)
})
//
app.use(express.static(path.join(__dirname, "build")))
app.get("*", (req, res) =>
res.sendFile(path.join(__dirname, "build/index.html"))
)
const port = process.env.PORT || 5000
app.listen(port, () => {
console.log(`Server started on port ${port}`)
})
对于动态站点,可以调用一个api,页面meta可以适当替换为信息。
我用 React 构建了一个博客,它从 api 中动态获取每个博客条目的数据。
该页面的内容显然根据路线看起来有所不同,例如mysite.com/blog/1
、mysite.com/blog/2
、...
我想要实现的是根据 url 从 api 获取的数据动态更改元描述。特别是 og:title
、og:description
和 og:image
。这样的事情甚至可能吗?
我阅读了有关 SSR/Next.JS 或 Gatsby 的信息,但我不确定如果从 api 调用接收到数据,这是否有效。
我知道 SSR 会在服务器上呈现内容,因此它允许 Google 抓取页面,但不会排除 api 调用吗? 我也明白 Gatsby 构建静态站点,但对我来说这行不通,因为 api 调用是动态的,不能构建到静态站点中。
我非常感谢能给我指明正确方向的提示。
I understand that SSR would render the content on the server, hence it allows Google to crawl the pages but wouldn't that exclude api calls? I also understand that Gatsby builds static sites but for me that wouldn't work because the api calls are dynamic and cannot be built into a static site.
我认为您误解了 Gatsby 的工作原理。
总而言之,Gatsby 从动态数据(API 调用)生成静态页面,因此,当您 运行 gatsby develop
或 gatsby build
命令时,Gatsby 会获取数据来自来源(在本例中来自您的 API)并生成动态页面(mysite.com/blog/1
、mysite.com/blog/2
等)。
此数据是静态的,这意味着这些来源的每次更改都会迫使您重新获取数据以显示更改(在生产中意味着新的部署)但是,一旦您的页面是静态构建的,您可以即时构建您的 SEO 数据。
这是他们以前在旧网站上使用的旧 Gatsby 工作流程,但我发现它非常不言自明:
在构建时,您的站点是静态生成的,因此您可以使用自定义 SEO 组件或您想要的任何内容完全自定义您的 SEO 要求。大多数启动器都带有一个可以使用的 SEO
组件:
function Seo({ description, lang, meta, title }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
const defaultTitle = site.siteMetadata?.title
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={defaultTitle ? `%s | ${defaultTitle}` : null}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata?.author || ``,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
].concat(meta)}
/>
)
}
由于该组件将 description
、lang
、meta
和 title
分别作为 props
,您可以将其添加到您的博客模板中获取将静态构建的动态数据,这意味着,当部署您的站点时,该数据已经构建,因此 Google 爬虫将立即获取它。
const YourBlogPostTemplate = ({ data }) =>{
return <article>
<SEO title={data.allAPIData.frontmatter.title} />
<h1>I'm the title: {data.allAPIData.frontmatter.title}</h1>
</article>
}
注意:我不会完全自定义它以避免扩展答案,但请理解。
SEO
组件将在构建时使用 title
和其余字段。
您的 API 调用是在页面构建之前获取的,因此,在构建页面时,您的数据已经是静态的。
有一篇非常好的文章 here 描述了如何以最简单的方式解决此问题。
基本上,我需要在我当前的 React 应用程序之上放置一个简单的 NodeJS 服务器。服务器现在提供构建目录中的文件。对于某些路由,我只是将 __PAGE_META__
占位符替换为 Google、Facebook、Twitter 等
这里用一张简单的图片来描述流程:
以及 NodeJS 部分的简单代码片段:
const path = require("path")
const express = require("express")
const app = express()
const fs = require("fs")
//
const pathToIndex = path.join(__dirname, "build/index.html")
app.get("/", (req, res) => {
const raw = fs.readFileSync(pathToIndex)
const pageTitle = "Homepage - Welcome to my page"
const updated = raw.replace("__PAGE_META__", `<title>${pageTitle}</title>`)
res.send(updated)
})
//
app.use(express.static(path.join(__dirname, "build")))
app.get("*", (req, res) =>
res.sendFile(path.join(__dirname, "build/index.html"))
)
const port = process.env.PORT || 5000
app.listen(port, () => {
console.log(`Server started on port ${port}`)
})
对于动态站点,可以调用一个api,页面meta可以适当替换为信息。