搜索引擎优化(SEO)与Next.js的支持

SEO介绍:Search Engine Optimization

什么是SEO

SEO 就是搜索引擎优化。SEO的目标是创建一个策略,以提高您在搜索引擎结果中的排名。排名越高,您网站的自然流量就越多,最终为您带来更多业务!

我们下面将探讨:

  • 搜索系统,以及谷歌机器人等搜索引擎机器人。

  • 拥有SEO策略可以对您的网站产生的影响。

  • 如何整合最佳SEO实践。

  • 使用 Next.js 进行爬网、索引、呈现和排名。

  • Web 性能主题,包括核心 Web 指标。

为什么SEO如此重要?

SEO是提高转化率和品牌信心的关键。更高的搜索排名位置等同于更多的自然访问者。搜索引擎自然流量 - 通过点击搜索引擎中的结果来到您网站的访问者 - 是许多商业的关键,原因有三:

  • 高质量 – 增加访客变成客户的机会。

  • 值得信赖 – 对您的品牌或使命更有信心。

  • 低成本 – 除了花费的时间和精力外,拥有良好的 SEO 实践可以带来更高的搜索引擎排名是免费的。出现在自然搜索结果的顶部位置没有直接费用。

优化的三大支柱

优化网站的过程可以分为三个主要支柱:

  • 技术 – 优化您的网站以提高抓取和网络性能。

  • 创建 – 创建内容策略以定位特定关键字。

  • 受欢迎程度 – 提高您网站的在线影响力,以便搜索引擎知道您是值得信赖的来源。这是通过使用反向链接来完成的——链接回您网站的第三方网站

SEO学科很广泛,有很多方面,但作为Next.js开发人员,第一步是了解如何通过一些最佳实践使您的Web应用程序为SEO做好准备。

搜索系统

搜索系统是你通常所说的搜索引擎(谷歌,必应,鸭鸭Go等)。它们是极其复杂的系统,可以解决技术史上一些最大的挑战。

搜索系统有四个主要职责

  • 爬行——浏览网络并解析所有网站内容的过程。这是一项艰巨的任务,因为有超过 3.5 亿个域名可用。

  • 索引——寻找存储在爬行阶段收集的所有数据的地方,以便可以访问。

  • 渲染——执行页面上的任何资源,例如可能增强网站功能和丰富网站内容的 JavaScript。这个过程不会发生在所有被抓取的页面上,有时它发生在内容被实际索引之前。如果当时没有可用资源来执行任务,则可能会在索引之后进行渲染。

  • 排名——查询数据以根据用户输入制作相关的结果页面。这是在搜索引擎中应用不同排名标准的地方,以便为用户提供实现其意图的最佳答案。

什么是网络爬虫

为了让您的网站出现在搜索结果中,Google(以及其他搜索引擎,例如 Bing、Yandex、Baidu、Naver、Yahoo 或 DuckDuckGo)使用网络爬虫来导航网站以发现网站及其网页。

不同的搜索引擎在每个国家拥有不同的市场份额。

在本指南中,我们介绍了 Google,它是大多数国家/地区最大的搜索引擎。也就是说,您可能需要查看其他搜索引擎及其指南,尤其是当您的目标客户位于中国、俄罗斯、日本或韩国时。

虽然在排名和呈现方面存在一些差异,但大多数搜索引擎在抓取和索引方面的工作方式非常相似

网络爬虫是一种模拟用户并通过网站上的链接导航以索引页面的机器人。网络爬虫使用自定义用户代理(User-Agent)来识别自己。 Google 有多种网络爬虫,但使用较多的是 Googlebot Desktop 和 Googlebot Smartphone。

以Googlebot 的工作原理为例,Googlebot 是 Google 的互联网爬虫,是搜索系统的一部分,它收集创建海量内容数据库以提供搜索结果所需的所有信息。

Googlebot 为网页编入索引的过程

该过程的一般概述如下:

  • 查找 URL:Google 从许多地方获取 URL,包括 Google Search Console、网站之间的链接或 XML 站点地图。

  • 添加到抓取队列:这些 URL 被添加到抓取队列以供 Googlebot 处理。 Crawl Queue 中的 URL 通常会在那里持续几秒钟,但视情况而定可能长达几天,特别是如果页面需要渲染、编入索引,或者——如果 URL 已经编入索引——刷新。然后页面将进入渲染队列。

  • HTTP 请求:爬虫发出 HTTP 请求以获取标头并根据返回的状态代码执行操作

  • 200 - 它抓取并解析 HTML。

  • 30X - 它遵循重定向。

  • 40X - 它将记录错误并且不加载 HTML

  • 50X - 它可能会稍后回来检查状态代码是否已更改。

  • 渲染队列:搜索系统的不同服务和组件处理 HTML 并解析内容。如果页面有一些基于 JavaScript 客户端的内容,则 URL 可能会添加到渲染队列中。渲染队列对谷歌来说成本更高,因为它需要使用更多资源来渲染 JavaScript,因此渲染的 URL 在互联网上的总页面中所占的百分比较小。其他一些搜索引擎可能不具备与 Google 相同的渲染能力,而这正是 Next.js 可以帮助您制定渲染策略的地方。

  • 准备好被索引:如果满足所有条件,页面可能有资格被索引并显示在搜索结果中。

抓取和索引

接下来我们来看看一下几个问题:

  • HTTP 状态代码基础知识。

  • 元数据以及网络爬虫在解析 Web 内容时查找的内容。

  • 如何与 Google 沟通,以便其搜索抓取工具知道您网站上何时有新内容。

  • 如何利用元机器人标签和规范链接向搜索引擎指示您想要的索引状态。

什么是HTTP 状态码(Status Codes)?

HTTP 响应状态代码指示特定 HTTP 请求是否已成功完成。有许多状态代码,但只有少数在SEO上下文中有意义。现在让我们来看看它们。

  • 200

表示请求已成功。

为了在谷歌上将页面编入索引,页面必须返回200状态码。这是您通常希望在页面中寻找的内容,以便它们获得自然流量。这是 Next.js 成功渲染页面时将设置的默认代码。

  • 301/308

HTTP 301 永久移动重定向状态响应代码指示请求的资源已最终移动到目标 URL。

这是一个永久重定向。通常,这是使用最广泛的重定向类型。

出于多种原因可以使用重定向,但最主要的是指示 URL 已从 A 点移动到 B 点。

需要重定向以确保,如果内容从一个地方移动到另一个地方,您不会失去当前和潜在的客户,并且机器人可以继续为您的网站编制索引

Next.js永久重定向默认使用308而不是301,因为它是较新的版本,被认为是更好的选择。

301和308两者间的主要区别在于301 允许将请求方法从 POST 更改为 GET,而308不允许。

您可以在 Next.js 中触发 308 重定向方法是在 'getStaticProps()' 函数中返回redirect重定向而不是 props。

export async function getStaticProps(context) {
  return {
    redirect: {
      destination: '/',
      permanent: true, // triggers 308
    },
  };
}

您还可以在 next.config.js 中设置的redirects集合: permanent: true 。

//next.config.js

module.exports = {
  async redirects() {
    return [
      {
        source: '/about',
        destination: '/',
        permanent: true, // triggers 308
      },
    ];
  },
};

  • 302

指示请求的资源已临时移动到目标 URL。

大多数情况下,302 重定向应该是 301 重定向。如果您将用户临时重定向到某个页面(例如促销页面),或者您根据位置重定向用户,则可能并非如此。

  • 404

指示服务器找不到请求的资源。

一般情况下,应使用 HTTP 301 状态代码将移动的页面重定向到新位置。如果未发生这种情况,URL 可能会返回 404 状态代码。

默认情况下,404状态代码不一定是坏的,因为如果用户碰巧访问不存在的URL,这是理想的结果,但它们不应该是页面中的常见错误,因为它可能导致搜索排名下降。

Next.js将自动为应用程序中不存在的 URL 返回 404 状态代码。

在某些情况下,您可能还希望从页面返回 404 状态代码。这时候可以通过返回以下内容来代替props来达到此目的:

export async function getStaticProps(context) {
  return {
    notFound: true, // triggers 404
  };
}

您可以通过创建 pages/404.js 创建一个在构建时静态生成的自定义 404 页面。

// pages/404.js
export default function Custom404() {
  return <h1>404 - Page Not Found</h1>;
}

  • 410

指示源服务器不再可以访问目标资源,并且此情况可能是永久性的。

这并不经常使用,但如果您要删除网站上不再存在的内容,则可能需要用到此状态代码。

使用 HTTP 410 消失可能是明智之举的示例包括:

  1. 电子商务: 商品已从库存中永久移除。

  1. 论坛:已被用户删除的话题。

  1. 博客:已从网站移除的博客文章。

此状态代码通知机器人不应再返回来对此内容进行爬网

  • 500

指示服务器遇到阻止其完成请求的意外情况。

Next.js将自动返回 500 状态代码,用于意外的应用程序错误。您可以通过创建 pages/500.js 来创建在构建时静态生成的自定义 500 错误页面。

// pages/500.js
export default function Custom500() {
  return <h1>500 - Server-side error occurred</h1>;
}

  • 503

指示服务器尚未准备好处理请求。

建议在网站关闭时返回此状态代码,并且您预测网站将在较长时间内关闭。这可以防止长期失去排名

什么是robots.txt文件

robots.txt是一个文本文件,用于指示网络爬虫(搜索引擎蜘蛛)哪些页面可以被访问,哪些页面不能被访问。该文件通常位于网站的根目录下,可以通过在浏览器中输入网站地址后加上“/robots.txt”来访问。该文件的作用是帮助网站管理员控制搜索引擎对网站内容的访问和抓取,保护网站的安全和隐私。

您可能希望保护网站的某些区域不被抓取并因此被索引,例如您的 CMS 或管理员、电子商务中的用户帐户或某些 API 路由等。

这些文件必须在每个主机的根目录中提供,或者您可以将根 /robots.txt 路径重定向到目标 URL,大多数机器人都会遵循。

由于 Next.js 中的静态文件服务我们可以轻松添加“robots.txt”文件。我们将在根目录中的public目录下创建一个名为“robots.txt”的新文件。

放置的内容的示例如下:

//robots.txt

# Block all crawlers for /accounts
User-agent: *
Disallow: /accounts

# Allow all crawlers
User-agent: *
Allow: /

注意:不要将public目录命名为任何其他名称。该名称无法更改,并且是唯一用于提供静态资源的目录。

XML 站点地图

站点地图是与 Google 沟通的最简单方式。它们会指示属于您网站的网址以及更新时间,以便 Google 可以轻松检测新内容并更有效地抓取您的网站。

尽管XML站点地图是最知名和最常用的站点地图,但它们也可以通过RSS或Atom创建,如果您更喜欢最大的简单性,甚至可以通过文本文件创建。

站点地图是一个文件,您可以在其中提供有关您网站上的网页、视频和其他文件以及它们之间的关系的信息。像谷歌这样的搜索引擎会读取此文件,以更智能地抓取您的网站。

根据谷歌,在以下情况下,您可能需要站点地图:

  • 您的网站非常大。因此,Google 网络抓取工具更有可能忽略抓取您的某些新网页或最近更新的网页。

  • 您的网站有大量内容页面存档,这些内容页面是孤立的或彼此链接不紧密的。如果您的网站网页没有自然地相互引用,您可以在站点地图中列出它们,以确保 Google 不会忽略您的某些网页

  • 您的网站是新的,几乎没有外部链接。Googlebot 和其他网络抓取工具通过跟踪从一个网页到另一个网页的链接来浏览网络。因此,如果没有其他网站链接到您的网页,Google 可能无法发现这些网页。

  • 您的网站包含大量富媒体内容(视频、图片)或显示在 Google 新闻中。如果提供,Google 可以在适当的情况下考虑站点地图中的其他信息以进行搜索。

虽然站点地图对于出色的搜索引擎性能不是强制性的,但它们可以促进抓取和索引到机器人,因此您的内容将被更快地拾取并相应地排名

强烈建议使用站点地图,并在您网站上填充新内容时使其动态化。静态站点地图也是有效的,但它们对Google来说可能不太有用,因为它不会用于持续的发现目的。

在Next.js项目中如何添加站点地图?

有两种选择:

  • 手动创建(简单的站点)

如果您有一个相对简单且静态的站点,则可以在项目的public目录中手动创建sitemap.xml:

<!-- public/sitemap.xml -->
   <xml version="1.0" encoding="UTF-8">
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <url>
       <loc>http://www.example.com/foo</loc>
       <lastmod>2021-06-01</lastmod>
     </url>
   </urlset>
   </xml>

  • 利用好getServerSideProps

您的网站更有可能是动态的。在这种情况下,我们可以利用getServerSideProps按需生成XML站点地图。

我们可以在页面目录中创建一个新页面,例如pages/sitemap.xml.js。此页面的目标是点击我们的 API 以获取数据,这些数据将使我们能够了解动态页面的 URL。然后,我们将编写一个 XML 文件作为 /sitemap.xml 的响应。

例如:

//pages/sitemap.xml.js
const EXTERNAL_DATA_URL = 'https://jsonplaceholder.typicode.com/posts';

function generateSiteMap(posts) {
  return `<?xml version="1.0" encoding="UTF-8"?>
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <!--We manually set the two URLs we know already-->
     <url>
       <loc>https://jsonplaceholder.typicode.com</loc>
     </url>
     <url>
       <loc>https://jsonplaceholder.typicode.com/guide</loc>
     </url>
     ${posts
       .map(({ id }) => {
         return `
       <url>
           <loc>${`${EXTERNAL_DATA_URL}/${id}`}</loc>
       </url>
     `;
       })
       .join('')}
   </urlset>
 `;
}

function SiteMap() {
  // getServerSideProps will do the heavy lifting
}

export async function getServerSideProps({ res }) {
  // We make an API call to gather the URLs for our site
  const request = await fetch(EXTERNAL_DATA_URL);
  const posts = await request.json();

  // We generate the XML sitemap with the posts data
  const sitemap = generateSiteMap(posts);

  res.setHeader('Content-Type', 'text/xml');
  // we send the XML to the browser
  res.write(sitemap);
  res.end();

  return {
    props: {},
  };
}

export default SiteMap;

搜索引擎的特殊Meta标签

Meta robots 标签是搜索引擎将始终遵守的指令。添加这些robots标签可以使您的网站索引更容易。

指令和建议之间是有区别的。Meta robots标签或robots.txt文件是指令,将始终遵守。规范标签是 Google 可以决定是否遵守的建议。

页面级meta标签有很多选项,但以下是通常与 SEO 相关的示例:

<meta name="robots" content="noindex,nofollow" />

robots标签

这可能是您将看到的最常见的标签。默认情况下它将具有 `index,follow` 值,因此不需要指定,'all'是有效的替代版本:

<meta name="robots" content="all" />

通过将robots标签设置为 `noindex,nofollow`,如上例所示,它将表明搜索引擎:

  • noindex(不索引)

页面不显示在搜索结果中。省略 noindex 将表示该页面可以编入索引并显示在搜索结果中。

构建网站时,您可能不希望将某些页面编入索引。常见用例包括:设置页面、内部搜索页面、策略等。

  • nofollow(不跟踪)

不点击此页面上的链接。省略nofollow将允许robots抓取并跟踪此页面上的链接。在其他网页上找到的链接可能会启用抓取功能,因此,如果链接 A 出现在 X 和 Y 网页中,并且 X 有 nofollow robots标签,但 Y 没有,Google 可能会决定抓取该链接。

Googlebot标签

<meta name="googlebot" content="noindex,nofollow" />

googlebot标签是特定于谷歌的。如果您希望为 Googlebot 制定单独的规则,并为其他搜索机器人制定通用规则,请使用此标记。

如果存在冲突的标记,则应用限制性更强的标记。

meta标签使您可以灵活地按需将页面标记为 noindex。

例如,如果您将过滤器应用于产品页面,但最终没有结果,则通常的做法是 noindex 此页面。

如果在网页已编入索引后添加规则,则网页可能会保持编入索引。确保网页未编入索引的最佳方法是使用“noindex”标记。

Google标签

nositelinkssearchbox

<meta name="google" content="nositelinkssearchbox" />

当用户搜索您的网站时,Google 搜索结果有时会显示一个特定于您网站的搜索框,以及指向您网站的其他直接链接。此标签nositelinkssearchbox告诉 Google 不要显示附加链接搜索框。

notranslate

<meta name="google" content="notranslate" />

当谷歌发现网站内容的语言不是用户可能想要阅读的语言时,谷歌通常会在搜索结果中提供指向翻译的链接。

通常,这使您有机会向更大的用户群提供独特且引人注目的内容。但是,可能存在不希望这样做的情况。这个meta标签告诉谷歌你不希望他们提供这个页面的翻译。

function IndexPage() {
  return (
    <div>
      <Head>
        <title>Meta Tag Example</title>
        <meta name="google" content="nositelinkssearchbox" key="sitelinks" />
        <meta name="google" content="notranslate" key="notranslate" />
      </Head>
      <p>Here we show some meta tags off!</p>
    </div>
  );
}

export default IndexPage;

可以看到,在Next.js中,我们正使用 Next/head,这是一个内置组件,用于将meta元素附加到页面的 head。

为了避免 head 中出现重复的标签,您可以使用 key 属性,这将确保标签只渲染一次。

什么是规范标签Canonical Tags?

规范网址是搜索引擎认为在您网站上的一组重复网页中最具代表性的网页的网址。

虽然您可以直接将规范网址传达给搜索引擎,但他们也可以决定在不通知您的情况下对多个网址进行分组。如果 Google 可以在多个不同的路径下找到网址,则可能会自动发生这种情况。

虽然谷歌在检测这些方面做得很好,但他们的系统可以大规模工作,并不能涵盖所有边缘情况。规范标签是涵盖您的网站的一个重要方面,以确保出色的性能。

如果 Google 发现多个网址具有相同的内容,则可能会决定在搜索结果中将其降级,因为它们可能被视为重复。

这也发生在跨域,如果您运行两个不同的网站并在每个网站中发布相同的内容,搜索引擎可以决定选择其中一个进行排名,或者直接降级两者

这就是规范标签非常有用的地方。他们让谷歌知道哪些网址是原始事实来源,哪些是重复的。跨相同或不同域的大量重复页面可能会导致排名不佳甚至受到处罚。

让我们想象一下,我们的电子商务商店允许通过 example.com/products/phone 和 example.com/phone 访问产品。

两者都是有效的有效网址,但我们使用规范网址来防止检测到我们拥有的重复内容。如果我们决定 https://example.com/products/phone 应该考虑排名,我们将创建一个规范标签:

<link rel="canonical" href="https://example.com/products/phone" />

规范标签是SEO性能的基础,因为不仅您可以创建不同的URL,而且用户或营销工具也可以创建它们。

想象一下,您正在Google上运行一些营销活动,然后Google决定添加一些UTM参数。Googlebot 可能会将这个新的唯一网址编入索引,因此您希望确保仍然显示规范标签以统一重复的网页

function IndexPage() {
  return (
    <div>
      <Head>
        <title>Canonical Tag Example</title>
        <link
          rel="canonical"
          href="https://example.com/blog/original-post"
          key="canonical"
        />
      </Head>
      <p>This post exists on two URLs.</p>
    </div>
  );
}

export default IndexPage;

渲染和排名

  • 渲染策略,例如客户端渲染 (CSR)、增量静态重新生成 (ISR)、静态站点生成 (SSG) 和服务器端渲染 (SSR)。

  • 静态站点生成 (SSG)

静态网站生成是HTML在构建时生成的。然后,此 HTML 将用于每个请求。静态网站生成可能是 SEO 的最佳渲染策略类型,因为您不仅可以在页面加载时拥有所有 HTML,因为它是预先渲染的,而且还有助于提高页面性能——现在是 SEO 的另一个排名因素

  • 服务器端渲染 (SSR)

与 SSG 一样,服务器端渲染 (SSR) 是预渲染的,这也使其非常适合 SEO。SSR 的 HTML 不是像 SSG 那样在构建时生成,而是在请求时生成。当您的页面非常动态时,这非常有用。

  • 增量静态重新生成 (ISR)

如果页面数量非常大,则在生成时生成所有页面可能不可行。Next.js允许您在构建网站后创建或更新静态页面

增量静态重新生成使开发人员和内容编辑者能够基于每个页面使用静态生成,而无需重新生成整个站点。借助 ISR,您可以保留静态的优势,同时扩展到数百万页

  • 客户端渲染(CSR)

客户端渲染允许开发人员使用 JavaScript 完全在浏览器中渲染他们的网站。在初始页面加载时,单个HTML文件通常几乎没有内容,直到您获取JavaScript并且浏览器编译所有内容为止。

正如我们上面评论的,一般来说,不建议使用客户端渲染来获得最佳 SEO。

CSR 非常适合数据密集型仪表板、帐户页面或任何您不需要在任何搜索引擎索引中的页面

  • 总结

对于SEO来说,最重要的是页面数据和meta数据可以在没有JavaScript的页面加载中可用。在这种情况下,SSG 或 SSR 将是您的最佳选择

Next.js的主要优势之一是上述每种渲染方法都可以按页面完成。您可能希望静态生成博客文章,渲染客户帐户仪表板客户端,然后您可能希望有一个要在服务器端渲染的新闻源。

  • AMP 网页怎么样?

2016 年,Google 开始使用 AMP 对网页进行搜索排名优先排序,AMP 是一种使开发人员能够创建在移动设备上加载速度更快的网页的技术,代价是要花时间去构建和维护它们。

随着核心网页指标网页体验更新,Google 放弃了 AMP 网页,这是在搜索轮播中显示的一项要求。这是谷歌在SEO目的方面对AMP的最后一个主要好处之一。

自 AMP 推出以来,Next.js 等新技术已经证明了其能够在不牺牲开发人员体验 (DX) 的情况下改善网站体验。

虽然 Next.js 提供 AMP 支持,但如果您的网站已获得较高的核心网页指标分数,请考虑权衡在您的网站中实施 AMP 的成本和收益。

  • URL 结构如何影响 SEO 排名。

URL结构是SEO策略的重要组成部分。虽然谷歌没有透露SEO的每个部分的权重,但无论它们最终是一个大还是小的排名因素,优秀的URL都被认为是最佳实践

您可能需要遵循一些原则:

  • 语义:最好使用语义网址,这意味着它们使用字词而不是 ID 或随机数。示例:/learn/basics/create-nextjs-app 优于 /learn/course-1/lesson-1

  • 合乎逻辑且一致的模式:网址应遵循某种在网页之间一致的模式。例如,您希望有一个对所有产品页面进行分组的文件夹,而不是为每个产品设置不同的路径。

  • 以关键字为中心:Google仍然将其系统的很大一部分基于网站包含的关键字。您可能希望在网址中使用关键字,以便于理解网页的用途。

  • 不基于参数:使用参数构建网址通常不是一个好主意。在大多数情况下,它们不是语义的,搜索引擎可能会混淆它们并降低它们在结果中的排名。

Next.js 中如何定义路由?

Next.js使用基于页面概念构建的文件系统路由。将文件添加到 pages 目录时,它将自动用作路由。pages目录中的文件和文件夹可用于定义最常见的模式。

让我们看一下几个简单的 URL 以及如何将它们添加到 Next.js 路由器:

对于博客或电子商务网站,您可能希望使用产品 ID 或博客名称作为 URL 的辅助信息域。这称为动态路由:

要使用动态路由,您可以在产品或博客子文件夹中的页面名称中添加方括号。

SSG例子:

// pages/blog/[slug].js

import Head from 'next/head';

export async function getStaticPaths() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://www.example.com/api/posts');
  const posts = await res.json();

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));
  // Set fallback to blocking. Now any new post added post build will SSR
  // to ensure SEO. It will then be static for all subsequent requests
  return { paths, fallback: 'blocking' };
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://www.example.com/api/blog/${params.slug}`);
  const data = await res.json();

  return {
    props: {
      blog: data,
    },
  };
}

function BlogPost({ blog }) {
  return (
    <>
      <Head>
        <title>{blog.title} | My Site</title>
      </Head>
      <div>
        <h1>{blog.title}</h1>
        <p>{blog.text}</p>
      </div>
    </>
  );
}

export default BlogPost;

SSR例子:

// pages/blog/[slug].js

import Head from 'next/head';
function BlogPost({ blog }) {
  return (
    <div>
      <Head>
        <title>{blog.title} | My Site</title>
      </Head>
      <div>
        <h1>{blog.title}</h1>
        <p>{blog.text}</p>
      </div>
    </div>
  );
}

export async function getServerSideProps({ query }) {
  const res = await fetch(`https://www.example.com/api/blog/${query.slug}`);
  const data = await res.json();

  return {
    props: {
      blog: data,
    },
  };
}

export default BlogPost;

  • 结合标题和内部链接以优化您的搜索引擎结果页面排名。

元数据

元数据是网站内容的摘要,用于将标题、描述和图像附加到网站。

  • title

title标签是最重要的SEO元素之一,主要有两个原因:

  1. 这是用户在点击从搜索结果进入您的网站时看到的内容。

  1. 这是谷歌用来了解你的页面的主要元素之一。建议在标题中使用关键字,因为它通常会提高搜索引擎中的排名位置。

<title>iPhone 12 XS Max For Sale in Colorado - Big Discounts | Apple</title>

此页面包含所有主要关键字,并且还使其对显示明确价值主张的用户具有吸引力:折扣(Discounts)!

  • description

description元标记是另一个重要的 SEO 元素但不如标题。根据谷歌的说法,这个元素不会在排名中考虑在内,但它会影响你在搜索结果上的点击率

使用说明元标记来补充商品信息中的信息。如果标题中有一些不适合的内容,请在此处使用更多关键字。如果用户的搜索包含这些关键字,则这些关键字将以粗体显示

<meta
  name="description"
  content="Check out iPhone 12 XR Pro and iPhone 12 Pro Max. Visit your local store and for expert advice."
/>

当它是搜索引擎结果页面(SERP)的一部分时,它在页面上的外观如下:

带有标题和描述的 SERP 片段示例

在Next.js中,我们在Head组件中设置标题和描述。这就是titledescription元标签在 Next.js 中的样子:

import Head from 'next/head';

function IndexPage() {
  return (
    <div>
      <Head>
        <title>
          iPhone 12 XS Max For Sale in Colorado - Big Discounts | Apple
        </title>
        <meta
          name="description"
          content="Check out iPhone 12 XR Pro and iPhone 12 Pro Max. Visit your local store and for expert advice."
          key="desc"
        />
      </Head>
      <h1>iPhones for Sale</h1>
      <p>insert a list of iPhones for sale.</p>
    </div>
  );
}

export default IndexPage;

可以在应用程序中的任何页面上使用 Head 组件来描述或提供有关页面内容的信息

  • open graph开放图形

Open Graph协议最初由Facebook开发,标准化了元数据在任何给定网页上的使用方式。您可以根据需要提供尽可能少或尽可能多的信息,但所有开放图形部分都组合在一起,以创建其附加到的站点的表示形式

其他社交媒体公司(如Pinterest,Twitter,LinkedIn等)也可能在共享URL时使用开放图形来显示丰富的卡片。Twitter也有Twitter卡片的标签。

虽然这些Open Graph标签与SEO相关标签有很多相似之处,但它们对搜索引擎排名没有任何好处,但仍建议使用它们,因为人们可能会在社交媒体或私人消息传递工具(如WhatsApp或Telegram)上分享您的内容

您可以通过在 Head 组件内的meta标记中定义“property”属性来添加 Open Graph 标记。例如:

import Head from 'next/head';

function IndexPage() {
  return (
    <div>
      <Head>
        <title>Cool Title</title>
        <meta name="description" content="Checkout our cool page" key="desc" />
        <meta property="og:title" content="Social Title for Cool Page" />
        <meta
          property="og:description"
          content="And a social description for our cool page"
        />
        <meta
          property="og:image"
          content="https://example.com/images/cool-page.jpg"
        />
      </Head>
      <h1>Cool Page</h1>
      <p>This is a cool page. It has lots of cool content!</p>
    </div>
  );
}

export default IndexPage;

拥有一个提供描述和标题的可共享链接,以及代表页面内容的图片不会对SEO排名产生直接影响,但它间接增加了链接的可点击性,最终将导致更多的访问者访问您的网站。

  • 结构化数据和 JSON-LD

结构化数据有助于搜索引擎了解您的页面。多年来,已经出现了几个词汇表,但目前主要的词汇表​​是 schema.org

Schema.org的词汇表可以与许多不同的编码一起使用,包括RDFa,Microdata和JSON-LD。

不同的搜索引擎可能会在 schema.org 内适应不同的词汇表,并且没有搜索引擎涵盖描述网站词汇的所有用例。请务必检查每种情况下接受哪些词汇表

添加 JSON-LD 产品架构数据的产品页面示例:

import Head from 'next/head';

function ProductPage() {
  function addProductJsonLd() {
    return {
      __html: `{
      "@context": "https://schema.org/",
      "@type": "Product",
      "name": "Executive Anvil",
      "image": [
        "https://example.com/photos/1x1/photo.jpg",
        "https://example.com/photos/4x3/photo.jpg",
        "https://example.com/photos/16x9/photo.jpg"
       ],
      "description": "Sleeker than ACME's Classic Anvil, the Executive Anvil is perfect for the business traveler looking for something to drop from a height.",
      "sku": "0446310786",
      "mpn": "925872",
      "brand": {
        "@type": "Brand",
        "name": "ACME"
      },
      "review": {
        "@type": "Review",
        "reviewRating": {
          "@type": "Rating",
          "ratingValue": "4",
          "bestRating": "5"
        },
        "author": {
          "@type": "Person",
          "name": "Fred Benson"
        }
      },
      "aggregateRating": {
        "@type": "AggregateRating",
        "ratingValue": "4.4",
        "reviewCount": "89"
      },
      "offers": {
        "@type": "Offer",
        "url": "https://example.com/anvil",
        "priceCurrency": "USD",
        "price": "119.99",
        "priceValidUntil": "2020-11-20",
        "itemCondition": "https://schema.org/UsedCondition",
        "availability": "https://schema.org/InStock"
      }
    }
  `,
    };
  }
  return (
    <div>
      <Head>
        <title>My Product</title>
        <meta
          name="description"
          content="Super product with free shipping."
          key="desc"
        />
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={addProductJsonLd()}
          key="product-jsonld"
        />
      </Head>
      <h1>My Product</h1>
      <p>Super product for sale.</p>
    </div>
  );
}

export default ProductPage;

在此示例中,数据被硬编码为字符串,但您可以轻松地将数据传递给“addProductJsonLd”方法以使其完全动态。

  • 站内搜索引擎优化

在高层级上,页面SEO是指构成页面整体结构的标题和链接。标题指示文档中的重要性,链接将 Web 连接在一起。

  • headings(标题)和H1

headings(标题)可帮助用户了解页面的结构以及他们将在接下来的段落中阅读的内容。它们还有助于搜索引擎了解页面的哪些部分是最重要的

headings标题从 h1 到 h6,h1 往往被认为是最重要的建议在每个页面中使用 H1 标题标签。H1 应代表页面的内容,并与您的标题标签相似。

function Page() {
  return <h1>Your Main Page Heading</h1>;
}

  • Internal Links 内部链接

互联网通过链接连接。如果没有从一个网站到另一个网站的链接,互联网可能就不会存在。接收更多链接的网站往往代表更受用户信任的网站

谷歌从PageRank算法的发明开始了这一原则。

在高级别上,PageRank算法是一种算法,它遍历数据库上的每个链接,并根据域接收的链接数量(数量)和域(质量)对域进行评分。来自垃圾邮件网站的大量链接很可能几乎没有价值。

然而,来自大型国家新闻网站的链接可能对搜索引擎非常有价值。这就是为什么链接很重要的原因,您应该始终在页面内部以及其他网站外部包含链接链接始终需要使用“href”才能用于PageRank计算

  • next/link

Next.js提供在路由之间启用客户端跳转的 Link 组件。一个简单的用例如下所示:

function NavLink({ href, name }) {
  return (
    <Link href={href}>
      <a>{name}</a>
    </Link>
  );
}

export default NavLink;

href 属性是必需的,并且会正确添加指向锚标签的链接,这对 SEO 至关重要。当Google抓取一个页面时,它将抓取并跟踪此链接,而不依赖JavaScript。

但是,如果 Link 的子组件是包装 a 标记的自定义组件,则必须将 passHref 添加到 Link。如果您使用的是 styled-components 等库,这是必需的。没有这个,a 标签将没有 href 属性,这会影响您网站的 SEO。

如何使用passHref的例子,如:

import Link from 'next/link';
import styled from 'styled-components';

// This creates a custom component that wraps an <a> tag
const RedLink = styled.a`
  color: red;
`;

function NavLink({ href, name }) {
  // Must add passHref to Link
  return (
    <Link href={href} passHref>
      <RedLink>{name}</RedLink>
    </Link>
  );
}

export default NavLink;

如果使用 ESLint,则 Next.js 有一个规则来防止这种情况发生。

网页性能和核心网页指标

网络指标是 Google 创建的一项计划,旨在提供统一的指导和指标来衡量最终用户在网络上的页面体验。

核心网页指标是网页指标的子集,目前由三个指标组成,用于衡量加载、交互性和视觉稳定性。这些指标是最大内容绘制 (LCP)、首次输入延迟 (FID)累积布局偏移 (CLS)

在这三个指标中取得高分将为您的用户创造更流畅的网站体验

网站在每个核心网页指标中得分较低将影响其搜索引擎排名,因为谷歌开始使用核心网页指标作为其搜索算法的排名因素。不良指标征会影响您的网络流量和业务。

衡量核心网页指标时有三种不同的值:"Good", "Needs Improvement", 和"Poor"。这些值因所测量的指标而异:

您可以通过两种不同的方式处理核心网页指标:

  • 尝试在每个指标上获得尽可能高的分数。追求完美固然很好,但在具有许多依赖项的大型网站上可能会很棘手。

  • 与您所在行业的竞争对手进行基准比较。您不会与Google搜索中的每个完美优化的网站竞争,而是与其他针对您的目标关键字排名的网站竞争

Largest Contentful Paint(LCP)

显示加载最大元素并向用户可见所需的时间。

最大内容绘制 (LCP) 指标着眼于页面的加载性能。LCP 测量在视窗中获取页面上最大元素可见所需的时间。这可能是占用页面上主要空间的大型文本块、视频或图像

注意:这不是首次内容绘制 (FCP),它测量从页面开始加载到第一个元素在屏幕上渲染的时间。

在DOM渲染时,页面上最大的元素可能会更改。在屏幕上看到最大的图像或元素之前,最大的内容绘制不会停止计数。

在屏幕上看到最大的图像或元素之前,最大的内容绘画不会停止计数。

First Input Delay (FID)

首次输入延迟 (FID) 指标是最终用户在与网页交互时的体验感知。想象一下,在输入框中单击只是什么都没有发生 - 这种对站点交互性和响应性的挫败感是由较大的输入延迟引起的。

FID需要真实的用户数据,不能在实验室(例如谷歌灯塔)中测量。但是,总阻塞时间 (TBT) 指标是实验室可衡量的,可以捕获影响交互性的问题。

当浏览器的主线程正在执行其他任务并且无法响应用户的请求时,就会发生 FID。

Cumulative Layout Shift (CLS)

Cumulative Layout Shift (CLS) 指标衡量网站的整体布局稳定性。在页面加载时意外改变布局的站点可能会导致意外的用户错误和分心。

累积布局偏移 (CLS) 发生在元素由 DOM 最初渲染后发生偏移时。在这里,一个按钮在文本块之后渲染到屏幕上,导致该块向下移动。计算 CLS 时会综合考虑影响和距离。

当新元素呈现到屏幕时,元素的位置发生改变会影响 CLS。

每个元素的单个布局偏移分数仅在发生意外移动时计入 CLS。如果将新元素添加到 DOM 或现有元素更改大小,则如果加载的元素保持其位置,则不计入布局偏移。


搜索引擎优化影响

谷歌搜索引擎的主要目标是在考虑到本地化和拼写错误的同时为用户提供最佳结果。在每种情况下,Google都关心为用户提供快速流畅的结果和出色的网站体验。

自 2018 年以来,移动设备上的网页速度一直是排名因素。但是,到目前为止,尚不清楚Google搜索算法使用哪些特定的性能指标作为排名的一部分。

这种情况在 2021 年 6 月发生了变化,当时 Google 提供了一组特定的指标和范围来分析和优化您的效果

  • Lighthouse (v6) Weights for Vitals

这三个指标的价值不一定相等。在Lighthouse灯塔中,为每个核心 Web 指标分配不同的权重:

  • Largest Contentful Paint: 25%

  • Total Blocking Time*: 25% (similar to First Input Delay)

  • First Contentful Paint: 15%

  • Speed Index: 15%

  • Time to Interactive: 15%

  • Cumulative Layout Shift: 5%

注意:对于所有核心网页指标的良好范围内的所有网页,无论其个人核心网页指标得分如何,Google 排名的影响都是相同的。

  • UX Impact(用户体验影响

围绕核心网络指标的大多数对话主要集中在SEO上。

虽然核心网页指标确实是一项旨在衡量和推动页面体验和搜索排名改进的计划,但最终从这些变化中受益的是用户。

核心网页指标有助于争取最佳的页面体验。根据亚马逊在 2012 年进行的一项研究,多一秒钟的加载时间可能会使该公司损失 16 亿美元。像这样的研究展示了出色的页面体验和快速网站的重要性,这两者都是核心网络指标帮助实现的。

提升核心网页指标得分的策略

让我们看看如何使用 Next.js 功能改进示例的核心 Web 指标。

  • Lighthouse 是什么以及我们如何使用它。

Lighthouse 通过对提供的 URL 运行一系列审计来工作。根据这些审计,它会生成有关页面执行情况的报告。如果有需要改进的地方,该报告将提供有关如何改进的见解。

让我们看一下灯塔报告的两个示例,以了解具有健康的核心网络指标的网站与没有健康网站指标的网站之间的区别。

优化的例子

要查看 Lighthouse 如何工作的示例,我们将使用我们的主页:https://nextjs.org。

  1. 打开浏览器。

  1. 隐身窗口中,导航至 https://nextjs.org。

  1. 打开 DevTools 并单击 Lighthouse 选项卡。

  1. 单击生成报告。

这现在将运行一个报告,该报告应该花费不到 60 秒。

注意:在隐身窗口中运行报告很重要,因为第三方插件会影响您的报告。

此外,广告拦截器可以阻止脚本加载,这会导致审核不完整。考虑设置一个干净的角色来衡量绩效。

未经优化的例子

要从 Lighthouse 获得准确的报告,应始终使用生产版本测试应用程序。要运行生产版本,请切换到项目目录:

运行 Chrome DevTools 的 Lighthouse 报告。报告完成后,就可以开始优化网站并改善各网页指标。

  • 如何使用 next/image 自动优化图像。

未优化的图像

使用常规 HTML,我们添加了我们的图像,如下所示:

<img src="large-image.jpg" alt="Large Image" />

但是,这意味着我们必须手动优化一些事情,例如:

  • 确保我们的图像在不同的屏幕尺寸上具有响应性。

  • 使用第三方工具或库优化我们的图像。

  • 在图像进入视窗时延迟加载图像

Image 组件

Next 提供了一个 Image 组件,可以为我们处理这些开箱即用的优化。

next/image 是 HTML img 元素的扩展,专为现代 Web 而发展。

这意味着可以使用 next/image 自动调整大小优化和提供现代格式(如 WebP)的图像(如果浏览器支持)。

该组件避免将大图像传送到具有较小视窗的设备,并允许 Next.js 采用未来的图像格式并将这些图像提供给支持它们的浏览器。

自动图像优化适用于任何图像源即使图像由外部数据源(如 CMS)托管,仍可对其进行优化

自动图像优化是如何工作的?

按需优化

Next.js 不是在构建时优化图像,而是在用户请求时按需优化图像。与静态站点生成器和纯静态解决方案不同,构建时间不会增加,无论是运送十张图片还是一千万张图片。

延迟加载图像

默认情况下图像是延迟加载的。对于位于视窗之外的图像,页面速度不会受到影响。图像仅在进入视图时加载。

避免累积布局偏移CLS

始终渲染图像以避免累积布局偏移 (CLS)。

使用Next的next/image 组件

让我们使用 next/image 更新应用程序以显示我们的图像。高度和宽度道具应为所需的渲染大小,宽高比应与源图像相同。

打开 pages/index.js 文件,并在文件开头添加来自next/iamge的图像导入:

// Before
<img src="large-image.jpg" alt="Large Image" />

// After
<Image src="/large-image.jpg" alt="Large Image" width={3048} height={2024} />

  • 如何动态导入库和组件以减少初始 JS 包。

  • 动态导入将减少从第三方库加载初始页面期间加载的 JavaScript 数量。

Next.js支持 JavaScript 的 ES2020 动态 'import()'。有了它,您可以动态导入JavaScript模块并使用它们。它们还适用于服务器端渲染 (SSR)。

将动态导入视为将代码拆分为可管理块的另一种方法。

打开 pages/index.js 文件并在文件开头删除这两个导入,因为我们将在文件下方动态导入它们。

让我们设置搜索输入以使用动态导入的库。

我们可以用以下代码替换输入:

/**
import Fuse from 'fuse.js';
import _ from 'lodash';
const fuse = new Fuse(countries, {
  keys: ['name'],
  threshold: 0.3,
});
**/
<input
  type="text"
  placeholder="Country search..."
  className={styles.input}
  onChange={async (e) => {
    const { value } = e.currentTarget;
    // Dynamically load libraries
    const Fuse = (await import('fuse.js')).default;
    const _ = (await import('lodash')).default;

    const fuse = new Fuse(countries, {
      keys: ['name'],
      threshold: 0.3,
    });

    const searchResult = fuse.search(value).map((result) => result.item);

    const updatedResults = searchResult.length ? searchResult : countries;
    setResults(updatedResults);

    // Fake analytics hit
    console.info({
      searchedAt: _.now(),
    });
  }}
/>

通过使用动态导入,这修复了页面加载时的“删除未使用的 JavaScript”问题。这也改善了我们的交互时间 (TTI),这有助于改善首次输入延迟 (FID)

  • 动态导入组件

React 组件也可以使用动态导入来导入,但在这种情况下,我们将它与 next/dynamic 结合使用,以确保它像任何其他 React 组件一样工作。

我们将使用此方法通过 Hello World 代码示例延迟加载我们的modal组件。通过这样做,我们还从初始页面加载中删除了另外两个第三方库。

打开 pages/index.js 文件,在文件开头添加 import for dynamic from next/dynamic

import dynamic from 'next/dynamic';
// remove this line
// import CodeSampleModal from '../components/CodeSampleModal';

// instead:import it as a dynamic component
const CodeSampleModal = dynamic(() => import('../components/CodeSampleModal'), {
  ssr: false,
});

CodeSampleModal 将是/components/CodeSampleModal返回的默认组件。它的工作方式类似于常规的 React 组件,可以像往常一样将 props 传递给它。

由于我们在服务器上不需要此组件,因此我们使用 ssr: false 来禁用它

接下来,我们希望推迟此组件的加载,直到用户需要它。为此,我们可以将组件包装在一个条件中,该条件检查modal是否应该打开,如果是,它将被加载。

包装 CodeSampleModal 组件,如下所示:

{
  isModalOpen && (
    <CodeSampleModal
      isOpen={isModalOpen}
      closeModal={() => setIsModalOpen(false)}
    />
  );
}

当 isModalOpen 第一次切换为 true 时,将请求所需的 JavaScript。

两个优化建议:

  • 使用 HTTP2:为了解决这个问题,我们可以部署到支持 HTTP2 的地方(例如 Vercel)。

  • 图像元素没有明确的宽度width和高度height:这实际上是灯塔中的一个错误,不会影响网站性能。

  • Next.js 如何默认优化网络字体加载。

优化字体:

自定义字体对于网站的品牌、设计和跨浏览器/设备的一致性非常重要。但是,使用 Web 字体不应以牺牲性能为代价。

Next.js内置了自动网页字体优化。默认情况下,Next.js 将在构建时自动内联字体 CSS,从而消除了获取字体声明的额外往返。这导致对首次内容绘制 (FCP) 和最大内容绘制 (LCP) 的改进

优化前,需要一个额外的请求:

<link href="https://fonts.googleapis.com/css2?family=Inter" rel="stylesheet" />

优化后,Next.js 会为你内联字体 CSS:

<style data-href="https://fonts.googleapis.com/css2?family=Inter">
  @font-face{font-family:'Inter';font-style:normal.....
</style>

  • 如何优化任何第三方脚本的加载。

优化第三方脚本

许多应用程序依赖于第三方 JavaScript 来包含不同类型的功能,例如分析、广告和客户支持小部件。但是,嵌入第三方创作的代码可能会延迟页面内容的呈现,如果加载得太早,可能会影响用户性能。

Next.js 提供了一个内置的Script组件,该组件优化了任何第三方脚本的加载,同时为开发人员提供了决定何时获取和执行它的选项。

  • 使用Script组件

使用常规 HTML,外部脚本需要手动附加到 next/head:

import Head from 'next/head';

function IndexPage() {
  return (
    <div>
      <Head>
        <script src="https://www.googletagmanager.com/gtag/js?id=123" />
      </Head>
    </div>
  );
}

使用 Next.js Script 组件,您可以将其添加到组件中的任何位置,而无需使用 next/head

import Head from 'next/head';
import Title from 'next/title';

function IndexPage() {
  return (
    <div>
      <Head>
        <Title>hello world</Title>
      </Head>
        <div>
          <Script
            strategy="afterInteractive"
            src="https://www.googletagmanager.com/gtag/js?id=123"
          />
        </div>
    </div>
  );
}

Script 组件引入了一个strategy属性,允许您决定何时获取和执行脚本以实现最佳加载。为了不对 Largest Contentful Paint (LCP) 产生负面影响,大多数第三方脚本应该在页面的所有内容完成加载后延迟加载,要么在页面变为交互后立即加载(strategy="afterInteractive"),要么在浏览器期间空闲时间延迟加载(strategy="lazyOnload")

监控核心web指标

优化站点后,在生产环境中进行监视非常重要,这样您就可以继续迭代优化。在监测核心 Web 指标时,随着时间的推移进行跟踪是关键,而不是依赖一次性的实验室测试。

Next.js分析

Next.js分析允许您使用核心网页指标分析和衡量网页的效果。

您可以在 Vercel 部署上以零配置开始收集您的真实体验分数。如果您是自托管,也是支持分析的。

自定义报告

也可以使用内置的中继器Next.js Analytics使用数据并将其发送到您自己的服务或将其推送到Google Analytics。

可以利用Next提供的reportWebVitals函数在控制台通过console.log实时查看指标。

打开pages/_app.js 文件并导出下面的reportWebVitals函数:

export function reportWebVitals(metric) {
  console.log(metric);
// 可以将其发送到您自己的服务或将其推送到Google Analytics
}

数据洞察(Chrome 用户体验报告)

另一种衡量性能的免费开源方法是使用 Chrome 用户体验报告数据集。

Chrome 用户体验报告提供了用户体验指标,说明真实情况下的 Chrome 用户如何体验网络上的热门目的地。

此数据集在 BigQuery下公开提供,您也可以在 Google Data Studio 下完全免费使用它。

幸运的是,您可以使用开源仪表板作为跟踪网站性能的模板。

此数据集的唯一缺点是,为了使您的网站包含在 CrUX 报告中,它需要具有有意义的访问量,否则由于缺乏数据,它不会包含在报告中。因此,对于正在进行的工作或最近创建的网站,这可能不是最佳选择

此外,数据每月更新一次。通常在一个月结束后的 15 天左右,因此您会延迟看到数据,如果您打算努力提高核心 Web 指标分数,这可能不是最实用的事情。

其他工具

您可以在以下工具中找到字段数据收集:

如果您正在寻找实验室数据,Google 还提供了几种测量工具:

  • Lighthouse:谷歌的开源自动化工具,用于提高网页质量。

  • Chrome DevTools:直接内置于Google Chrome浏览器中的一组Web开发人员工具。

请注意,对于这两种工具,您都需要使用总阻塞时间 (TBT) 作为首次输入延迟 (FID) 的替代方法,因为 FID 只能通过现场数据进行测量。

猜你喜欢

转载自blog.csdn.net/u011024243/article/details/129471076
今日推荐