使用 Next.js SSG 技术实现博客网站标签页功能

Leo
Leo
Cover Image for 使用 Next.js SSG 技术实现博客网站标签页功能
  1. 基本原理:
  2. 操作步骤

Next.js是一个基于React的服务端渲染框架,提供了一种简单的方式来创建静态站点,同时也支持动态内容。在本文中,我们将使用Next.js SSG(静态站点生成)技术来为博客网站添加标签,并实现点击标签后跳转至同一标签的文章列表。

基本原理:

  • 在博客文章的 meta 数据中添加 tags 字段,用于存储文章的标签信息。

  • 使用Next.js SSG技术生成静态站点时,遍历所有文章,将每个标签作为一个路由,生成对应的静态页面。

  • 在标签页面中,使用 getStaticProps 方法获取所有包含该标签的文章,并渲染出文章列表。

  • 给文章的标签添加 Link 属性,点击后可以跳转。

Next.js提供了两个静态生成方法 getStaticProps 和 getStaticPaths ,用于生成静态站点。其中,getStaticProps 方法用于获取静态页面的数据, getStaticPaths 方法用于生成所有静态页面的路由。

使用静态生成的好处是可以提高网站的性能和SEO,因为静态页面可以被缓存,不需要每次请求都重新生成。 getStaticProps 和 getStaticPaths 方法是Next.js实现静态生成的核心方法。

getStaticProps 方法用于获取静态页面的数据,它会在构建时被调用,只会在服务器端运行。在构建时,Next.js会预先渲染所有静态页面,并将其缓存起来。当用户访问该页面时,直接从缓存中读取,不会再次调用getStaticProps方法。getStaticProps方法的返回值必须是一个对象,该对象包含props属性,用于传递数据给页面组件。示例代码如下:


export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
};
}

getStaticPaths方法用于生成所有静态页面的路由,它会在构建时被调用,只会在服务器端运行。在构建时,Next.js会预先生成所有静态页面的路由,并将其缓存起来。当用户访问该页面时,直接从缓存中读取,不会再次调用getStaticPaths方法。getStaticPaths方法的返回值必须是一个对象,该对象包含paths属性,用于指定所有静态页面的路由。示例代码如下:


export async function getStaticPaths() {
const data = await fetchData();
const paths = data.map((item) => ({
params: { id: item.id },
}));
return {
paths,
fallback: false,
};
}

fallback属性用于指定是否启用fallback模式,如果启用,则表示该路由不存在时,会动态生成该页面,否则会返回404页面。

使用getStaticProps和getStaticPaths方法可以实现动态路由和静态生成的结合,可以在不牺牲性能和SEO的情况下,实现动态内容的展示。

操作步骤

  • 在博客文章的 meta 中添加tags字段,例如:
blog.mdx
Copy

export const meta = {
title: '使用 Next.js SSG 技术实现博客网站标签页功能',
description: `本文介绍了如何使用Next.js SSG(静态站点生成)技术`,
date: '2023-03-24T23:00:00+08:00',
authors: [levon],
tags: ['react','ssg'],
coverImage: card
}

  • 在项目中创建/pages/tags目录,并在该目录下创建 [tagName].jsx 文件,例如:

/pages/tags/[tagName].js

  • 在 [tagName].jsx 文件中,使用getStaticPaths方法生成所有标签的路由:
[tagName].jsx
Copy

// Generates `/tags/1` and `/tags/2` ...
export async function getStaticPaths() {
const allPosts = await getAllPosts(); // 获取所有文章
const tags = new Set(); // 使用Set去重
allPosts.forEach((post) => {
post.tags.forEach((tag) => {
tags.add(tag);
});
});
const paths = Array.from(tags).map((tag) => ({
params: { tagName: tag },
}));
return { paths, fallback: false };
}

  • 在[tagName].js文件中,使用getStaticProps方法获取所有包含该标签的文章:
[tagName].jsx
Copy

export async function getStaticProps({ params }) {
const allPosts = await getAllPosts();
const posts = allPosts.filter((post) => post.meta.tags.includes(params.tagName));
return {
props: {
tagName: params.tagName,
posts,
},
};
}

  • 在[tagName].js文件中,渲染当前标签下的文章列表:
[tagName].jsx
Copy

import Link from 'next/link';
import { getAllPosts } from '../../lib/api';
export default function TagPage({ tagName, posts }) {
return (
<Layout>
<TagHeader tag={tagName} />
<div className="grid md:grid-cols-1 gap-8">
{posts.map(({ slug, meta }) => (
<PostCardHor key={slug} meta={meta} slug={slug} />
))}
</div>
</Layout>
);
}

  • 最后一步,我们需要再文章页面给文章的tag组件添加Link属性:
tagItem.jsx
Copy

const TagItem = ({ tag }: Props) => {
const tagContent = preDefineTags.find((t) => t.key === tag)?.displayName || tag;
return (
<Link href={`/tags/${tag}`}>
<span className={`inline-block mt-5 text-xs font-medium tracking-wider uppercase hover:underline ${tagColor(
tag
)}`}
>
{tagContent}
</span>
</Link>
);
};

以上就是使用Next.js SSG技术为博客网站添加标签,并实现点击标签后跳转至同一标签的文章列表的操作步骤。