Nextjs 网站SEO优化 1.0

437 阅读6分钟

业务需要对项目进行seo搜索优化,seo有很多中的内容,这次也是分为了多期开发, 第一次主要从下面几个方面进行调整:

  1. URL优化
  2. 页面的meta标签和关键词的优化
  3. 301重定向

还有其他的内容, 比如增加页面的内容 丰富性也能提升排名。

学无止境,但是头发有。

一、URL优化

网站搭建的初期没有考虑到seo优化这个方向,所以在路由设计上有很多问题,路由的调整是非常大的(如果要做seo建议一开始就做好后续的迭代坑位)

产品是某招聘软件,可以根据地址和招聘类型进行查询,之前是按照我们的业务模块进行的地址定义,这样不能准确的的被爬取到,因此,路由改变和地址转义是第一步。

文件目录的改变,因为next的特性,目录就是路由,所以第一步就是要改目录名称

这样在浏览器上访问的时候就是最新, 我们是招聘软件,因此命名是跟招聘有关的,其他行业可以使用其他的命名。

我们可以通过这样的地址去访问到对应的页面

第二个是参数的问题,我们采用城市+类型的形式去拼接我们的地址,因为我们的筛选参数是从地址获取的。

举个栗子,这样的地址代码我们是在找成都区域的程序员工作,这就是我们的最终的url类型格式

1、地址转义

地区肯定是以行政编码为准,因此我们需要维护一个地址库

里面有拼音、中文和行政编码的对照关系,因为后面的meta需要使用到中文,所以需要有这个中文的对照,至于需不需要很详细看业务需求。

用户看到的是拼音地址,meta标签中用的是中文,后面会说,传递给后端的是行政码。

还需要一些配套的方法来拿到对应的拼音或者行政码:

当然这个看自己设计,精细一点可以把方法封装深一点,根据不同参数取不一样的数据

通过这些方法我们可以拿到地址的信息,便于后面的meta标签和jsonLd数据等的拼接。

至于后面的参数拼接,则根据自己的实际需求来做就行了,这里就不说了。

举例:

首页:https://www.xxx.cn/【城市拼音】——其他信息

// 列表
https://www.xxx.cn/xx1/chengdu_chengxuyuan
规则:https://www.xxx.cn/xx1/【城市名字拼音】_【其他的参数信息】

// 详情  我们是地址栏拼接了参数的,根据自己的需求来
规则:https://xxx.cn/xxxx1/[id/标识/或者其他信息].html?type=xx&code=123

地址转移,自己其他地方取参数也是一致的,定义自己的规则就行了。

2、301优化

301优化,我们没有www 域名,所以需要做一个域名转发,

文档中也有写:nextjs.org/docs/app/ap…

就是再next.config.js 中新加一个配置项。但是具体规则还是要根据自己的网站需求来

xxx.cn/22333/www.xxx.cn/chengdu/

 // // 301优化
  async redirects() {
    return [
      {
        source: '/:path*',
        has: [
          {
            type: 'host',
            value: 'xxx.cn',
          },
        ],
        destination: 'https://www.xxx.cn/:path*',
        permanent: true,
      },
    ];
  },

二、页面Meta标签

页面meta标签是必须的,可以简单也可以难一点,根据自己需求来就好了。

我们采用的next.js实现的,所以自己写再html肯定不显示

还是根据文档来:nextjs.org/docs/app/bu…

官网提供两个,一个是静态,就是不需要加入参数,直接放在我们的组件前面就好了,

是放在服务端组件哦,不要放在客户端去了。

1、静态meta

内容是写死的,基本没啥配置的能力

import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: '解签下江南',
  description: 'SEOmeta讲解',
  keywords:"关键词"
}
 
export default function Page() {}

最终再浏览器渲染出来:

有很多中的meta标签,按照自己的需求配置就行。

如果是ts的话们可以从 Metadata 类型点击进去,就可以看到支持的类型 。

<title>解签下江南</title>
<meta name="description" content="SEOmeta讲解" />
<meta name="keywords" content="关键词" />

image.png

2、动态meta

顾名思义,里面的数据可以变化,根据url的不同或者其他内容去切换和更改meta显示的

import type { Metadata, ResolvingMetadata } from 'next'
 
type Props = {
  params: Promise<{ id: string }>
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
 
export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  // 这里拿到的就是我们的路由参数
  const id = (await params).id
   
  // fetch data
  // 如果有一些数据需要根据后台请求去或者再这里可以定义
  const product = await fetch(`https://.../${id}`).then((res) => res.json())
 
  // optionally access and extend (rather than replace) parent metadata
// 这个就是一些图片数据
  const previousImages = (await parent).openGraph?.images || []
 
  return {
    title: product.title,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}
 
export default function Page({ params, searchParams }: Props) {}

看了上面的例子相信你也看出了一些,异步其实最终还是返回一个meta对象,只不过他的对象内容可以自己去组装,根据路由参数,或者请求的数据去切换,针对不同的页面可以修改成对应的针对信息。

我们的项目做了抽取


type Props = {
  params: Promise<{ code: string }>;
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  // const code = (await params).code;
  const code = await params;
  return getHeadMeta(code, META_TYPE)! as Metadata;
}

方法内部实现:

export const getHeadMeta = (
  param: Record<string, string>,
  type: META_TYPE,
  searchParam: { [key: string]: string | string[] | undefined } = {},
) => {
  // 根据传入的参数,返回对应类型的headmata标签
  let titleContent = "解签下江南";
  let descriptionContent = "seo";
  let keywordsContent = "关键内容";

  switch (type) {
    case META_TYPE.x: //首页
      return {
        title: "解签下江南",
        description:"解签下江南",
        other: {
          "applicable-device": "pc",
          renderer: "webkit",
        },
        ...COMMON_META_SCRIPT,
        alternates: {
          canonical: `https://www.xxx.cn/${param.code || ""}`,
        },
      };

    case META_TYPE.xx1: //特殊页面根据页面信息进行一些内容切换
      const Address = param.code.split("_")[0];
      const { name }: AddressData =
        getAddressData(zhaopinAddress)!;
      titleContent = `${name}解签下江南`;
      descriptionContent = `${name}seo`;
      keywordsContent = `${name}解签下江南`;

      return {
        title: titleContent,
        description: descriptionContent,
        keywords: keywordsContent,
        other: {
          "applicable-device": "pc",
          renderer: "webkit",
        },
        ...COMMON_META_SCRIPT,
        alternates: {
          canonical: `https://www.xxxx.cn/xxx1/${param.code}`,
        },
      };
      。。。。。
    // 官网下载页等。。。。
    case META_TYPE.OTHER_PAGE: //
      return {
        title: "解签下江南",
        description:"解签下江南",
      };

    default://兜底选择
      return {
        title: "解签下江南",
        description:"解签下江南",
        other: {
          "applicable-device": "pc",
          renderer: "webkit",
        },,
      };
  }
};

http-equiv 属性内容写在head中

image.png

再head中添加script标签

因为直接这样使用会被检测出语法错误

 <script type="application/ld+json">
                        {
           "@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld",
            "@id": "https://www.xxx.cn/",
           "title": "解签下江南",
             "description": "解签下江南"
          }
                </script>

需要转义一下,用模板字符串多重包裹

<script type="application/ld+json">
        {`{ "@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld",
          "@id": "https://www.xxx.cn/",
          "title": "解签下江南!",
          "description": "解签下江南"
        }`}
      </script>

根据不同的参数去判断该使用那些meta,例如官网就该是 xxx官网, 如果是网站就可以放一些 啥网站之类的描述

这样就达到了我们的动态meta的要求

3、JSON-LD

文档:nextjs.org/docs/app/bu…

很多网站都有生成一个jsonld的sciprt标签

boss

小米官网:

里面也是放一些信息标签

这个内容也是再服务端组件,放在,我们的组件代码中,最终生成是再html的head里面

我们也是做了抽取的,因为next的机制问题,每个页面都要用一下

const jsonLd = getJsonLd(META_TYPE, paramData);

return (
  <>
  <script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
    />
    <div> xxx内容</div>
  <>
  )

方法内部:


// 返回一个jsonLd对象
export const getJsonLd = (
  type: META_TYPE,
  param: Record<string, string | number | undefined>,
) => {

  switch (type) {
    case META_TYPE.HOME_PAGE:
      const address = getAddressRegionName(param.region as string);
      const metaContent = {
        title: "解签下江南",
        description:"解签下江南",
      };


      return {
        "@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld",//百度的链接
        "@id": `https://www.xxx.cn/${addressPronunciation}`,
        title: `${metaContent.title}`,
        description: `${metaContent.description}`,
      };
      其他的类型跟meta一致。
    。。。
      // 默认
    default:
       return {
        "@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld",//百度的链接
        "@id": `https://www.xxx.cn/${addressPronunciation}`,
        title: `${metaContent.title}`,
        description: `${metaContent.description}`,
      };
      break;
  }
};

这样我们就可以添加了,这个看需求,需要就加,不需要就不加。

4、next提供的Script标签

这里再开始的时候没注意看文档,直接搜的script,出来了这个标签

文档:nextjs.org/docs/app/ap…

最开始就以为这个可以实现jsonld。

试了一下发现,这样生成的script标签是在body中的,使用角度不一样。

使用用法你们自己去摸索吧。

三、百度代码和robots

1、robots

next是再public中加一个就行。

内容看个人需求:

User-agent: *
Allow: /xx1/
Allow: /xx2/
Disallow: /*?*

注意的是,next会自动生成这个文件

因此,如果要个性化的话就要关闭自动生成配置

next-sitemap.config.js 文件中的 generateRobotsTxt 配置要确保是false

不然就会自己生成,导致我们加的不生效。

/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: "https://xx1.cn",
  generateRobotsTxt: false,  // 关闭配置!!!!
  exclude: ["/test"]
};

2、百度代码

最外层的layout文件中,需要添加这一段,自己去百度的监控平台注册,把自己的网站上传上去就行。

这样百度才能爬去到

四、页面内链优化

所有可以点的的链接都用a标签包起来,next提供组件,link组件就是a标签封装的,所以可以直接使用a标签的属性

文档:nextjs.org/docs/app/ap…

本次分享就到此为止,我也是初入,以后有机会继续更新。

=========== =========== =========== ===========