构建期分页:静态站的翻页为什么不该用查询参数
列表分页在构建时切成静态页,第 N 页是一个真实路由。没有客户端分页逻辑,也不用查询串,翻页就是纯链接跳转。
这个站的博客列表每页 6 篇。第二页的地址是 /zh/blog/page/2/,一个构建期生成的真实 HTML 文件,而不是 /zh/blog/?page=2。
为什么不用查询参数
静态托管下,?page=2 对服务器和爬虫都是同一个 HTML。分页内容要么靠 JS 在客户端切——那意味着首屏得拿到全部文章数据,把性能优势交回去;要么让服务器读查询串——那就不是纯静态了。构建期切页绕开了这两个选项。
页码怎么收敛
切片与页码收敛是纯逻辑,放在 lib/paginate.ts,零 import:
export function paginate(items, page, size) {
const total = totalPages(items.length, size);
const current = clampPage(page, total);
const start = (current - 1) * step;
return {
items: items.slice(start, start + step),
page: current,
totalPages: total,
hasPrev: current > 1,
hasNext: current < total,
};
}
超范围的页码收敛到末页,而不是返回空页;size 非法时按 1 页处理,免得除零。这些分支都有断言覆盖。
路由由篇数推导
server/paths.ts 的 blogPagedPaths 按总篇数算出要生成几页,第 1 页是列表页本身,不重复生成。加一篇文章,新页自动出现,不用手写路由。
组件只在多页时渲染
只有一页时 pagination 是 null,分页组件整体不渲染,页面底部也不会多出一排孤零零的「1」。
代价
每页一份 HTML,文章变多时页面数线性增长;翻页是整页跳转,不保留任何筛选状态。这个站不需要筛选,所以第二条不构成损失。

评论
…