发布于 2022-08-14, 更新于 2024-07-08
作为博客站点,从 SEO 等角度,HTML 代码预生成的能力是必须的。由于成本考虑,博客一直使用 PHP 虚拟主机,所以一直使用了 PHP 的服务端渲染。
但是 PHP 视图层的开发体验,与现有的前端生态较难接轨,开发效率不佳。在了解 Next.js 时,看到了静态页面生成 SSG (Static Site Generation) 的方案,这让我眼前一亮。
用了几个小时的试验,成功将视图层从 PHP 升级到了 Next.js。
使用 npx create-next-app@latest 快速创建了 ts 的项目模板,结合 Pre-rendering and Data Fetching官方文档教程,很快的将博客列表页、详情页渲染了出来。
比如,对于博客的列表页,创建 /posts/${page} 规则的路由。这里为了减少 DOM 渲染,还是保留了分页逻辑。
在 getStaticPaths 中,计算一共需要生成多少个“列表页”。先拉去总共的文章数量,每 20 篇文章生成一个列表页。
interface Params extends ParsedUrlQuery {
page: string;
}
export const getStaticPaths: GetStaticPaths<Params> = async () => {
let { totalPage } = await getPostList({ page: 1, count: 20 });
return {
paths: Array.from({ length: totalPage }).map((_, index) => {
return {
params: { page: (index + 1).toString() },
};
}),
fallback: false,
};
};
在 getStaticProps 中,为每个页面拉取数据,比如第 5 页,就会去接口拿第五页的 20 篇文章进行渲染。
export const getStaticProps: GetStaticProps<PostListProps, Params> = async (context) => {
const { page } = context.params! as Params;
let { posts, current, pageSize, totalCount } = await getPostList({
page: Number(page) || 1,
count: 20,
});
return {
props: {posts, current, pageSize, totalCount,},
};
};
通过这样的数据获取,在构建时,页面组件会接受入参,进行渲染和处理即可。
export default function PostDataListPage({ posts, current, pageSize, totalCount }: PostListProps) {
return <div> ... </div>;
}
对于动态搜索,也是必不可少的。 SSG 方案的妙处在于,它会将入参数据生成为 json 文件,能作为动态数据处理。
在文章列表页的基础上,提取了文章列表、分页等样式作为文章列表样式组件,在原有的 pages 下只做数据处理,并创建 /pages/search 页面用于处理搜索:
const router = useRouter();
const [data, setData] = useState<Post[]>([]);
const [page, setPage] = useState(1);
const getData = () => {
let val = router.query.v.toLocaleLowerCase();
setData(
posts.filter((item) => {
return (
item.title.toLocaleLowerCase().includes(val) ||
item.remark.toLocaleLowerCase().includes(val) ||
item.content.includes(val)
);
}),
);
setPage(1);
};
useEffect(() => {
getData();
}, [router.query.v, posts]);
const limitNum = (page - 1) * 20;
const viewPosts = data.slice(limitNum, limitNum + 20);
在文章数据不多的情况下,这个搜索方案也可以获得较快的速度。
本次视图层的升级,开发体验和站点性能都得到了较大提升。
开发体验:
站点性能:
由于构建是在本地进行,所以本地始终会保留一份最新的静态站点和 JSON 数据,也算是一种数据备份。
在 博客升级到 Next.js 14 ,迁移到 app 路由,升级 SSG 模式 文章 SSG 升级 中说明。