開発2026-06-20
静的データと DB の二重ソースは、新規の DB 分が一覧から孤児になる
一覧やトップを静的ファイルだけで描き、詳細ページだけ DB を見る構成にすると、DB に足した新規コンテンツがどこからもリンクされず孤児になる。一覧側を静的+DB のマージに寄せて解決する。
DB に新しい記事を足したのに、サイトのどこからもたどり着けない。ページ自体は開けるのに、一覧にもトップにも関連リンクにも出てこない。データソースが二重になっているのが原因だった。
事象
- DB に追加した新規コンテンツの詳細ページは、直接URLを叩けば開ける
- だが一覧・トップ・関連リンクのどこにも出てこない
- 内部リンクが 0 なので、回遊もされないしクローラーにも見つかりにくい
原因
データの読み元が 2 つに割れていた。
- 一覧・トップ・関連:静的ファイル(例:
data/articles.ts)だけを読んで描画 - 詳細ページ:DB を優先して描画
この構成だと、DB にだけ足した新規分は、詳細ページには存在するのに一覧側の静的データには載っていない。結果、どこからもリンクされない「孤児」になる。
// ❌ 一覧は静的データonlyを読む
import { articles } from '@/data/articles';
export function listArticles() {
return articles; // DBの新規分が入らない
}
気づきにくいのは、詳細ページが普通に開けてしまうからだ。「ページはあるのに導線がない」状態は、ぱっと見では正常に見える。
解決策
一覧側を「静的 + DB のマージ」に寄せる。小さな fetch ヘルパーにまとめておくと、トップ・一覧・関連・sitemap が同じソースを共有できる。
// ✅ 静的 + DB をマージして返す
export async function fetchAllArticles() {
const fromDb = await db.getPublishedArticles();
const merged = new Map<string, Article>();
// 静的を入れてから DB で上書き(slug衝突は DB 優先)
for (const a of staticArticles) merged.set(a.slug, a);
for (const a of fromDb) merged.set(a.slug, a);
return [...merged.values()].sort(
(a, b) => +new Date(b.date) - +new Date(a.date)
);
}
slug がぶつかったら DB を優先、最後に日付の降順で並べる。これで新規 DB 分も一覧に出るし、内部リンクが張られる。
補足
- sitemap も同じマージ結果から生成する。一覧と sitemap がずれると、片方にしか出ないページが生まれる
- 「詳細は開けるのに一覧に出ない」は、データソースが割れているサインとして覚えておくといい
※ 本記事にはアフィリエイトリンクが含まれます。