🧚

Next.js App Router で実践した SEO & Core Web Vitals 改善

に公開

はじめに

自分のポートフォリオサイト(Next.js 15 + App Router)を
名前検索で 1 位表示 & Core Web Vitals オールグリーン
にするまでに行った 10 の施策をまとめます。


TL;DR

カテゴリ やったこと 成果
メタ generateMetadata で title/description/keywords を 3 言語動的生成 CTR↑
構造化データ Person & WebSite JSON-LD 追加 リッチリザルト候補
URL 設計 セクションを独立ページ化 (/about, /research …) クローラビリティ↑
Sitemap app/sitemap.ts で全言語×全ページ自動生成 Index Coverage 100%
Robots /robots.txt 自動生成 クロール最適化
i18n next-intl + サブパス (/ja, /en, /zh) 多言語 SEO ベストプラクティス
画像 next/image + priority LCP 改善
フォント Google Fonts display:"swap" & preconnect FOIT 回避
コード分割 dynamic() で下層ページ遅延ロード JS バンドル 25% 削減
Analytics GA4 を <Script strategy="afterInteractive"> で挿入 CLS 0

1. generateMetadata を完全活用

title=src/app/[locale]/layout.tsx
export async function generateMetadata({ params }: { params: { locale: string } }): Promise<Metadata> {
  const metaByLocale = { ja: {...}, en: {...}, zh: {...} };
  const m = metaByLocale[params.locale] ?? metaByLocale.ja;

  return {
    ...m,
    openGraph: {
      url: "https://ryosh.in",
      images: ["https://ryosh.in/logo.png"],
    },
    twitter: { images: ["https://ryosh.in/logo.png"] },
  };
}
  • keywords「指名+肩書+大学名+専門領域」 の組み合わせで作成
  • 画像 URL は絶対パスでないと無効になるので注意

2. JSON-LD でリッチリザルトを狙う

title=src/components/StructuredData.tsx
<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{ __html: JSON.stringify(getPersonData(locale)) }}
/>

@type:"Person" に SNS・論文・スキルを盛り込み、
@type:"WebSite"SearchAction を追加してサイト内検索もアピール。


3. ハッシュではなくページとして分割

  • 理由: Google は #about を別ページとは認識しない
  • 実装: src/app/[locale]/about/page.tsxAboutSection を配置
  • Navigationnext/linkrouter.push("/ja/about")

4. Sitemap をコードで自動生成

title=src/app/sitemap.ts
const locales = ["ja","en","zh"] as const;
const pages   = ["","about","research","skills","projects","gallery"] as const;

export default function sitemap(): MetadataRoute.Sitemap {
  return locales.flatMap(locale =>
    pages.map(p => ({
      url: `https://ryosh.in/${locale}${p&&"/"+p}`,
      lastModified: new Date(),
      priority: p==="" ? 1 : 0.9,
    }))
  );
}

5. Core Web Vitals 改善ポイント

指標 Before After 対策
LCP 2.9 s 1.7 s 画像 priority + Hero のみ初期ロード
CLS 0.12 0.00 GA4 script を遅延読み込み
JS 170 kB 128 kB dynamic() でコード分割

6. Vercel へのデプロイを自動化

# release ブランチに push → CI
npm run build
vercel deploy --prod --yes

7. 参考リンク


おわりに

指名検索だけなら最低限でも上位表示できますが、
「研究テーマ」「技術スタック」まで拾ってもらうには 構造化データと多言語メタ が効きます。
ポートフォリオをお持ちの方はぜひ試してみてください!

Discussion