在 React 应用中处理 SEO

2025-06-07

在 React 应用中处理 SEO

最初发表在我的博客上

我已成功抵达巴厘岛,租了一辆摩托车,享受着从我住处到巴厘岛 Dojo 的旅程,我现在正在那里写这篇文章。

SEO定义

搜索引擎优化 (SEO) 是提高网站流量的质量和数量,提高网站或网页对网络搜索引擎用户的可见性的过程。

摘自维基百科

SPA 问题与 SEO 神话

所有使用 CRA(create-react-app)或 Gatsby 构建的用于提供动态内容的 React 应用都是单页应用,这意味着只有一个 index.html 文件来呈现应用的内容,也就是说,组件内的所有元标记都不会被搜索引擎抓取进行索引,而以前是这样的!自 2019 年 5 月起,谷歌宣布其爬虫现在可以像 Twitter/Facebook/Slack/Telegram 爬虫一样抓取 JavaScript 代码,所以当非技术人员提到这个 SPA SEO 误区时,一定要让他们明白。

在爬虫能够抓取 JavaScript 之前,我们所做的

大多数 React 开发人员使用 Next Js,因为它提供服务器端渲染,这意味着当用户访问某个 URL 时按需生成页面,或者使用一种称为预渲染的技术,这基本上是在构建时进行的服务器端渲染,Gatsby 仍然使用这种方法为你的静态内容生成页面,但不为动态内容提供该功能,不像 Netlify 等某些服务为你的动态内容提供预渲染。

SEO组件

这个 GitHub 存储库(包含您需要在标题标签中包含的所有内容)的启发,我制作了这个 SEO 组件,我几乎在所有 Gatsby/React 应用程序中重复使用它来处理 SEO

我在代码中添加了一些注释来解释每个部分

import React from 'react'
import Helmet from 'react-helmet'

// This is the thumbnail that appears when someone shares your website
import Thumbnail from 'assets/me.jpg'
import {
  url,
  defaultTitle,
  defaultDescription,
  social,
  socialLinks,
  address,
  contact,
  legalName,
  foundingDate,
  logo,
  author,
} from 'data/config'

export const SEO = ({
  title,
  type,
  description,
  articleBody,
  datePublished,
  dateModified,
  cover,
  location = '',
  readTime,
}) => {

// This is Structured data that is recommended to have according to Google
  // You can read more about it on Google's own documentation about structured data
  // The first string is for the Article schema and the second one for the organization schema
  const structuredDataArticle = `{
        "@context": "http://schema.org",
        "@type": "${type}",
        "mainEntityOfPage": {
            "@type": "WebPage",
            "@id": "https://google.com/article"
        },
        "headline": "${description}",
        "image": "${
      cover ? `https://smakosh.com${cover}` : `https://smakosh.com${Thumbnail}`
    }",
        "datePublished": "${datePublished}",
        "dateModified": "${dateModified}",
        "author": {
            "@type": "Person",
            "name": "${author}"
        },
        "articleBody": "${articleBody}",
        "publisher": {
            "@type": "Organization",
            "name": "${author}",
            "logo": {
                "@type": "ImageObject",
                "url": "${logo}"
            }
        },
        "description": "${description}",
        "url": "${url}${location}/?ref=smakosh.com"
  }`

  const structuredDataOrganization = `{
        "@context": "http://schema.org",
        "@type": "${type}",
        "legalName": "${legalName}",
        "url": "${url}",
        "logo": "${logo}",
        "foundingDate": "${foundingDate}",
        "founders": [{
            "@type": "Person",
            "name": "${legalName}"
        }],
        "contactPoint": [{
            "@type": "ContactPoint",
            "email": "${contact.email}",
            "telephone": "${contact.phone}",
            "contactType": "customer service"
        }],
        "address": {
            "@type": "PostalAddress",
            "addressLocality": "${address.city}",
            "addressRegion": "${address.region}",
            "addressCountry": "${address.country}",
            "postalCode": "${address.zipCode}"
        },
        "sameAs": [
            "${socialLinks.twitter}",
            "${socialLinks.google}",
            "${socialLinks.youtube}",
            "${socialLinks.linkedin}",
            "${socialLinks.instagram}",
            "${socialLinks.github}"
        ]
    }`

  return (
    // Notice I'm using react-helmet to inject these elements within the header tag
    <Helmet>
      {/* The description that appears under the title of your website appears on search engines results */}
      <meta name="description" content={description || defaultDescription} />

      {/* The thumbnail of your website */}
      <meta
        name="image"
        content={cover ? `${url}${cover}` : `${url}${Thumbnail}`}
      />

      {/* Opengraph meta tags for Facebook & LinkedIn */}
      <meta property="og:url" content={`${url}${location}/?ref=smakosh.com`} />
      <meta
        property="og:type"
        content={type === 'NewsArticle' ? 'NewsArticle' : 'website'}
      />
      <meta
        property="og:title"
        content={title ? `Smakosh | ${title}` : defaultTitle}
      />
      <meta
        property="og:description"
        content={description || defaultDescription}
      />
      <meta
        property="og:image"
        content={cover ? `${url}${cover}` : `${url}${Thumbnail}`}
      />

      {/* You can get this id when you create an app id on Facebook of your Facebook page */}
      <meta property="fb:app_id" content={social.facebook} />

      {/* These tags work for Twitter & Slack, notice I've included more custom tags like reading time etc... */}
      <meta name="twitter:card" content="summary" />
      <meta name="twitter:creator" content={socialLinks.twitter} />
      <meta name="twitter:site" content={social.twitter} />
      <meta
        name="twitter:title"
        content={title ? `Smakosh | ${title}` : defaultTitle}
      />
      <meta
        name="twitter:description"
        content={description || defaultDescription}
      />
      <meta
        name="twitter:image:src"
        content={cover ? `${url}${cover}` : `${url}${Thumbnail}`}
      />
      {type === 'NewsArticle' && (
        <meta name="twitter:label1" value="Reading time" />
      )}
      {type === 'NewsArticle' && (
        <meta name="twitter:data1" value={`${readTime} min read`} />
      )}
      {type === 'NewsArticle' && (
        <meta name="author" content="Ismail Ghallou" data-react-helmet="true" />
      )}
      {type === 'NewsArticle' && (
        <meta
          name="article:published_time"
          content={datePublished}
          data-react-helmet="true"
        />
      )}

      {/* Structured data */}
      <script type="application/ld+json">
        {type === 'NewsArticle'
          ? structuredDataArticle
          : structuredDataOrganization}
      </script>

      {/* Not sure if this is still relevant as Google shut down their Google+ paltform */}
      <link rel="publisher" href={socialLinks.google} />

      {/* The title of your current page */}
      <title>{title ? `Smakosh | ${title}` : defaultTitle}</title>

      {/* Default language and direction */}
      <html lang="en" dir="ltr" />
    </Helmet>
  )
}
Enter fullscreen mode Exit fullscreen mode

我将其包含在每个组件中,使其像页面一样

import React from 'react'
import SEO from './SEO'

export default () => (
  <div>
    <SEO title="Home page" location="/" type="Organization" />
    <h1>Home page</h1>
  </div>
)
Enter fullscreen mode Exit fullscreen mode

您可以从本博客的代码源中获取此组件。

提高网站在搜索结果中排名的技巧和工具

如果您的网站是像本网站这样的博客,强烈建议使用像这样的RSS 提要,因为某些应用程序和扩展程序会抓取提要并为您带来更多访问者,从而提高您在搜索结果中的排名。

拥有站点地图也有帮助,您必须将其提交到您的Google 搜索控制台

您可以在此处测试您的结构化数据

请随意在评论部分提出您的问题,我会尽力回答所有问题。

文章来源:https://dev.to/smakosh/handling-seo-in-react-apps-32ae
PREV
使用 React 加快页面速度✨
NEXT
Tailwind CSS - 使用 React、Vue、Svelte 和 Angular 编写的免费入门程序