この
記事数が
最近は
PVの 集計方 法を ざっくり振り返る
PV機能を
その
しかし、
現在は
Redisの
pageviews:${NODE_ENV}:${slug}の形式で キーを 保存している - インクリメント時は
IPアドレスを ハッシュ化して 保存し、 n秒間重複して 計測されないように チェックしている - n秒経過すると、
その キーバリューは 消滅する
キーに
PVの 多い 順に 取得する 方 法
人気記事を
- キーに
紐づく データを 全て 取得 ( mget)する sortで昇順に 並び替える
これだけ。
const getAllPageViewsSorted = async () => { const prefix = `pageviews:${env.NODE_ENV}:`; const keys = postMetadataForEdge.map(({ slug }) => `${prefix}${slug}`);
if (keys.length === 0) { return []; }
const values = await redis.mget<number[]>(...keys);
const pageViews = keys.map((key, index) => ({ slug: key.replace(prefix, ""), views: values[index] ?? 0, }));
pageViews.sort((a, b) => b.views - a.views);
return pageViews;};当初はscanmget
PVは
毎回 APIが 走らないように する
PVは
import { unstable_cache } from "next/cache";
export const getCachedAllPageViewsSorted = unstable_cache( async () => getAllPageViewsSorted(), undefined, { revalidate: 60 * 60, },);キャッシュにはunstable_cacheをunstable(不安定)と
unstable_cacheを
キャッシュされた
話は
記事一覧を 表示
PVが
const popularPostCount = 6;
export const PopularPosts = async ({ className }: { className?: string }) => { const allPageViewsSorted = await getCachedAllPageViewsSorted(); const popularPosts = allPageViewsSorted .slice(0, popularPostCount) .map(({ slug }) => getPostBySlug(slug) as Post);
return ( <div className={cn( "grid grid-cols-2 gap-3 sm:grid-cols-3 xl:gap-4", className, )} > {popularPosts.map((post, index) => ( <div key={post._id} className="relative"> <ArticleCard post={post} /> <RankNumber rank={index + 1} /> </div> ))} </div> );};上記のslugを
UIは
Data Cacheの
さい ごに
人気記事を