分类: seo

  • Next.js 14 SEO 最佳实践(2)Next.js 14 SEO 要点

    Next.js 14 SEO 最佳实践(2)Next.js 14 SEO 要点

    继续分享 Next.js 14 SEO 最佳实践。上次主要介绍 SEO 基础知识,以及一般原则,这次重点放在 Next.js 14 上。我先武断暴言一句:Vercel 在 Next.js 14 上的整了个烂活儿,给开发者留下了很大的坑要填。

    页面组件避免 'use client'

    Next.js 14(也可能更早,待查)引入了 serverclient 组件的区分。前者没有状态,渲染一次后就不会变化;后者则可以与用户互动,响应用户操作,并将变化体现在视图之中。

    SEO 有一些必备信息,包括 title, description,需要通过 export const metadatagetMetadata 返回。它们都不支持 client 组件,所以,我们应该避免让页面组件(page.tsx)成为 client

    按照官方文档的说法,client 组件也会在服务器端进行渲染,然后发给客户端,所以比较合适的做法是:

    1. 组件化颗粒度可以细一些,以便将不需要状态的 server 组件和响应用户操作的 client 组件进行隔离。
    2. 必要的数据,尤其是希望搜索引擎抓取并索引的数据,在页面组件里完成读取,然后传递给 client 组件,作为初始值,完成第一次 SSR。
    3. getMetadata 时,可以使用 React.cache 函数将结果缓存起来,重复使用,降低网络请求成本
    4. 限制 client 的功能比较多,比如 createContext,所以工具函数文件不妨也分离得细一些,避免产生影响。

    确保返回页面 metadata

    SEO 需要一些信息来理解页面,并在搜索时呈现给用户,这些信息基本上都要通过 metadata 提交给搜索引擎,所以我们应该保证在 page.tsx 里都有返回合适的 metadata

    一般来说,metadata 需要包含以下数据,后面的代码简单演示了动态获取并返回信息的方式:

    1. 页面 title
    2. 页面内容 description
    3. OpenGraph 信息
    4. Canonical link
    5. 如果有多语言,还应该有 alternate link
    export async function generateMetadata(
    { params, searchParams }: PracticeDetailPageProps,
    parent: any
    ): Promise<Metadata> {
    // 读取路由参数
    const courseId = params.courseId;

    // 这里的加载函数可以提前 cache,以避免重复请求 API
    const courseDetail =
    await webApi.courseApi.fetchCourseDetail<CourseDetailType>(courseId);

    const metadata: Metadata = {
    title: courseDetail.title,
    description: courseDetail.description,
    alternates: {
    canonical: `https://www.hackquest.io/practices/${courseId}`
    },
    openGraph: {
    title: courseDetail.title,
    description: courseDetail.description,
    image: courseDetail.thumbnail,
    },
    };

    return metadata;
    }

    增加组件颗粒度,创造条件使用 server 组件

    因为静态内容更有利于 SEO,而 server 组件是生成静态内容的最好方式,所以我们应该尽量多使用 server 组件。

    问题在于 client 组件具有传染性,当某个组件内部使用状态的时候,它就必须是 client 组件,所以我们应该尝试让组件颗粒化的程度更细,仅在需要交互的组件里使用状态。

    搜索引擎的爬虫可以沿着超链接爬取一个又一个页面,而它们并不知道某个 <div> 上绑定了跳转事件,所以应该使用 <Link> 帮助搜索引擎索引整个网站。

    很多时候,为满足埋点等需求,我们会使用 onClick 事件,没关系,因为事件会先于链接跳转触发,所以我们只需要正常使用埋点功能即可。

    全站使用统一的通用导航

    使用全站通用的顶部导航和底部导航是提升 SEO 和网页收录的好办法。

    通用导航里面可以包含大量站内链接,方便搜索引擎爬虫遍历整个网站,所以我们应该在通用导航里大量使用 <Link> ,让爬虫可以顺藤摸瓜,找到我们网站里的全部内容。当然,从用户角度的来说,通用导航可能并不是每次打开页面的主要目的,所以,通过 CSS 控制通用导航的显示状态,让爬虫可以按图索骥,但是不影响普通用户阅读网页,是我们应该做的。

    所以,我们应该让整个网站使用统一的导航内容,只调整显示状态,而不是每个页面显示不同的导航。

    分离工具函数和依赖,避免污染

    影响 client 组件的因素很多,比如各种 hooks,createContext,等。如果我们在 a 函数里使用了这些功能,然后在 bimport a,会导致 b 也必须是 use client。这就要求我们尽量将引用的工具函数进行分离,比如单独写一个 utils.client.ts 用来存放客户端才需要使用的工具函数。

    使用 [[...slug]] 处理 URL

    如同前面所说,我们应该给所有资源配置好合适的 URL。比如我们有一些博客内容,需要建立博客页面,那么,我们就应该给翻页功能分配好独立的 URL,如 /p/${page},而不是把翻页状态保存在页面状态里。同样,如果我们支持按标签、分类筛选,就可以提供 /tag/${tag-slug} 这样的 URL。

    此时,为了能更好的复用代码、复用组件,我们可以用可选通配符组件 [[...slug]] 来制作页面。

    const Blog: React.FC<BlogProps> = async function ({
    searchParams = {},
    params: { slug = [] }
    }) {
    const limit = 12;
    const minPage = Number(slug[1]) < 1 ? 1 : Number(slug[1]);
    const page = slug[0] === 'p' ? minPage : 1;

    // 处理加载分页后的博客数据
    ....
    }

    制作 robots.txtsitemap.xml

    制作 robots.txt 比较简单,很多时候手写一个放到 /public 目录里即可,所以我不再赘述。

    制作 sitemap.xml 就复杂很多,因为网站可能会有很多页面,其中更有不少需要动态生成,所以我们一般需要创建 sitemap.ts 才能完成。部署的时候,构建脚本会自动调用这个文件,生成新的 sitemap.xml

    详情请参考官方文档:Generating a sitemap using code (.js, .ts)

    小结

    如果你对 Next.js 或者 SEO 有什么问题和想法,欢迎留言讨论。

    本站目前还在招商:本站广告 2024 年招商,欢迎感兴趣的老板私信洽谈。

    系列文章

    系列长文好更不好看,所以我决定以后都在 notion 上做汇总页,方便日后整体阅读。本文实际已经基本写完了,感兴趣的同学可以先去围观:https://meathill.notion.site/Next-js-14-SEO-90d31eee22ff4621af6620524b4b2773?pvs=4

  • Next.js 14 SEO 最佳实践(1)了解 SEO,常规要点

    Next.js 14 SEO 最佳实践(1)了解 SEO,常规要点

    近日搞 SEO 比较多,本来想写篇“Nuxt3 SEO 最佳实践”,但是列完大纲,发现内容不太够,基本上只需要照搬各种 SEO 手册,跟 Nuxt3 关系不大,不符合我对内容的要求。然后我自信满满地想帮朋友搞 Next.js 14 SEO,发现,好难,Next.js 14 的坑真多……于是就有了这系列文章。

    什么是 SEO

    SEO 即搜索引擎优化(Search Engine Optimization),是指通过优化网站以提高网站在搜索引擎中的自然排名,从而增加网站流量,提高品牌曝光度的一系列操作。SEO 主要关注两个方面:站内优化与站外优化。站内优化包括确保网站的结构、内容质量、关键词布局、网页元标签、URL结构等对搜索引擎友好。而站外优化则更多关注于外部链接建设,即增加其他网站对你的网站的链接,这有助于提高网站的权威性和排名。

    作为技术人员我们一般会负责站内优化,本文也主要讨论站内优化。

    为什么要 SEO?

    1. SEO 目前仍然是最便宜的流量来源。
    2. SEO 跟用户体验并不冲突,事实上,搜索引擎一直在想办法把用户体验和搜索排名结合起来。
    3. 我们甚至可以以 SEO 之名,为优化网站争取开发时间

    现代 SEO 的注意事项

    作为一名前端/全栈开发,有一些东西归属于我们的同事,比如创建内容、扩展外链,我们可以不过分深究。但是也有一些注意事项,尽早注意,可以节省大量返工的时间。

    了解必要的知识

    本文主要是我的经验之谈,不是很全面,更多的知识请阅读后面扩展阅读里的各个链接。

    尽量用服务器端渲染

    1. 服务器渲染对 SEO 更加友好。
    2. 对于大部分搜索引擎爬虫来说,如果能采用静态分析,性能会比分析 JS 渲染的页面高很多。
    3. 服务器端渲染对用户体验也有提升。

    尽量用超链接而不是手动跳转

    1. 浏览器爬虫可以通过超链接 <a> 找到更多页面。
    2. onclick 无法做到这一点。
    3. 我们仍然可以使用 onclick 进行数据埋点统计,因为事件会早于链接跳转触发。

    给每个资源一个 URL

    1. 为了能够在用户间共享,以及让搜索引擎可以索引,我们需要给每个资源一个 URL。
    2. 比如一个页面,如果它包含翻页,我们应该给所有页面安排 URL,比如 /p/2/p/3 等等。而不是把状态保存在浏览器内存里,因为这样外界没法获取直接指向它的资源。
    3. 如果是音频、视频等需要长时间播放的资源,则可以利用锚点: #{时间} 来指向某个具体的时间点。长网页上的标题也应使用类似的锚点技术。
    4. 总之,尽量不要在内存里保存状态,都搞成 URL,做成超链接

    确保页面上有合适的 SEO 内容

    1. <title>
    2. <meta name="description" content="{description}" />
    3. <link ref="canonical" href="{canonical link}" />
    4. <link hreflang="{语言}" href="{其它语言链接}" />
    5. 使用 og 库添加 OpenGraph 信息
    6. 大量可以被搜索引擎阅读和理解的文本,少用图片
    7. 图片、音频、视频等,要配备 alt 等文本信息
    8. 使用 aria-* 帮助搜索引擎链接页面
    9. 使用超链接时,使用 rel 来告诉搜索引擎链接目标和本页面的关系

    尽量把内容全部展示出来

    1. 搜索引擎希望能一次抓取所有内容,这样它才能正确地索引全部内容,以及爬取剩下的内容。
    2. 有时候我们基于页面容量,会倾向于把一些内容隐藏起来,等待用户满足特定条件才展开。比如 tab、carousel 等。此时,我们最好使用 CSS 控制显示效果,而不是只输出部分内容。
    3. 当然,如果涉及到付费墙、私密信息等,可以不显示所有内容。

    设计良好的 URL 结构

    1. 良好的 URL 可以帮助搜索引擎理解我们的内容结构
    2. 也拿博客举例:
      1. / 首页
      2. /p/{page} 分页
      3. /tag/{tag-slug} 分类页
      4. /cate 分类页面
      5. /cate/sub-cate/ 子分类页面
      6. /cate/sub-cate/page-slug-一般来说是内容 具体文章页

    其它

    1. 生成正确的 robots.txtsitemap.xml 并提交给搜索引擎
    2. 避免 404 和 500
    3. 利用缓存改进访问速度
    4. 保证使用 heading,但不要滥用 heading 标题,确保 h1~h6 的合理顺序

    小结

    如果你对 Next.js 或者 SEO 有什么问题和想法,欢迎留言讨论。

    本站目前还在招商:本站广告 2024 年招商,欢迎感兴趣的老板私信洽谈。

    系列长文好更不好看,所以我决定以后都在 notion 上做汇总页,方便日后整体阅读。本文实际已经基本写完了,感兴趣的同学可以先去围观:https://meathill.notion.site/Next-js-14-SEO-90d31eee22ff4621af6620524b4b2773?pvs=4