Blog

静的サイトの詳細ページに「最新のお知らせ」を共通表示する方法

2026年07月28日

Web

お知らせの詳細ページ下部に、「最新のお知らせ」を数件表示したいことがあります。

HTMLファイルをサーバーへアップロードして公開している静的サイトでは、新しいお知らせを追加するたびに、過去の詳細ページも更新する方法が最初に思いつきます。

ページ数が少ないうちは問題ないものの、記事が増えると全ページを更新する対応は難しくなります。そこで今回は、お知らせ情報をまとめたJSONファイルをJavaScriptで読み込み、各詳細ページへ最新のお知らせを共通表示する方法を整理します。

先に結論

制作者側でお知らせを追加し、HTMLを手動でアップロードする運用であれば、次の構成にすると更新対象を絞れます。

お知らせの元データ
↓
最新のお知らせ数件をJSONファイルとして出力
↓
各詳細ページからJavaScriptで取得
↓
ページ下部へカードを生成して表示

新しいお知らせを公開するときに更新するのは、基本的に次の2つです。

  • 新しいお知らせ詳細ページ
  • 最新のお知らせ数件をまとめたJSONファイル

各詳細ページが同じJSONファイルを読み込むため、JSONを更新すれば、過去のページに表示される最新のお知らせもまとめて変わります。

方法を選ぶ前に比較する

同じ「最新のお知らせを表示する」要件でも、更新する人と公開方法によって適した構成は変わります。

方法 向いているケース 更新時に触る範囲 注意点
HTMLを直接更新する ページ数・更新頻度が少ない 新しいページと過去の全詳細ページ 更新漏れが起きやすい
JSONとJavaScriptで表示する 手動アップロードのまま、過去ページの更新を減らしたい 新しいページとJSON JavaScript実行後に表示される
ビルド時にHTMLへ埋め込む サイト全体を自動ビルド・自動公開できる 元データだけ ビルド・公開の仕組みが必要
CMSを利用する 担当者が更新し、下書きや予約公開も必要 CMSの管理画面 管理・保守する仕組みが増える

この記事で扱うのは、2つ目の「JSONとJavaScriptで表示する」方法です。

あまりWeb制作に詳しくない依頼者がJSONを直接編集する運用には向きません。制作者側で生成やアップロードを管理でき、CMSを追加するほどの更新機能は必要ない案件で検討します。

実装手順

手順1:HTMLに表示先の枠を置く

各詳細ページには、固定の見出しと一覧の挿入先を用意します。

<section class="latest-news" data-latest-news-section>
  <div class="latest-news__heading">
    <h2>最新のお知らせ</h2>
    <a href="/news/">お知らせ一覧へ</a>
  </div>

  <ul class="latest-news__list" data-latest-news></ul>
</section>

<script src="/assets/js/latest-news.js" defer></script>

見出しや一覧ページへのリンクなど、変わらない部分はHTMLに残します。繰り返し表示する各お知らせカードは、JavaScript側で生成します。

手順2:最新のお知らせをJSONで用意する

JSONには、表示に使う情報だけを含めます。

[
  {
    "title": "夏季休業のお知らせ",
    "date": "2026-07-28",
    "url": "/news/2026/07/summer-holiday/"
  },
  {
    "title": "Webサイトを更新しました",
    "date": "2026-07-20",
    "url": "/news/2026/07/renewal/"
  }
]

JSONはブラウザーから取得できる公開ファイルです。本文、管理用ID、下書き状態など、公開する必要がない情報は含めません。

配信用のファイルをnews-min.jsonのように分けておくと用途が分かりやすくなります。ただし、minは圧縮済みという意味ではなく、表示に必要な項目だけに絞ったファイルという意味です。

手順3:JavaScriptでJSONを取得して表示する

各詳細ページでは、JavaScriptのfetch()を使ってJSONを取得します。

news-min.json
        ↓ fetch()
各お知らせ詳細ページ
        ↓
最新のお知らせ数件を表示

実装例は次のとおりです。slice(0, 4)の数値を変えれば、表示件数を調整できます。

async function renderLatestNews() {
  const list = document.querySelector("[data-latest-news]");

  if (!list) {
    return;
  }

  try {
    const response = await fetch("/data/news-min.json");

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const items = await response.json();
    const fragment = document.createDocumentFragment();

    items.slice(0, 4).forEach((item) => {
      fragment.append(createNewsItem(item));
    });

    list.replaceChildren(fragment);
  } catch (error) {
    console.error("最新のお知らせを取得できませんでした。", error);

    document
      .querySelector("[data-latest-news-section]")
      ?.remove();
  }
}

function createNewsItem(item) {
  const li = document.createElement("li");
  li.className = "latest-news__item";

  const link = document.createElement("a");
  link.className = "latest-news__link";
  link.href = item.url;

  const time = document.createElement("time");
  time.className = "latest-news__date";
  time.dateTime = item.date;
  time.textContent = item.date.replaceAll("-", ".");

  const title = document.createElement("span");
  title.className = "latest-news__title";
  title.textContent = item.title;

  link.append(time, title);
  li.append(link);

  return li;
}

renderLatestNews();

記事タイトルなどのデータを扱うため、文字列をinnerHTMLへまとめて入れるのではなく、textContentを使って要素を生成しています。意図しないHTMLとして解釈されることを避けるためです。

手順4:静的サイトジェネレーターからJSONを生成する

手作業でJSONを編集すると、HTMLだけ更新してJSONを更新し忘れる、URLや日付を二重入力して間違えるといったミスが起こりやすくなります。

お知らせを静的サイトジェネレーターで管理しているなら、元データから配信用JSONを自動生成する方が安心です。ここでは11tyを例にしますが、元データから公開用JSONを生成する考え方は、Astroなど静的出力に対応したツールでも共通です。コレクションの取得方法や出力方法は、それぞれの構成に合わせて読み替えます。

ビルド時には、次の処理を行います。

  1. 公開済みのお知らせだけに絞る
  2. 公開日の新しい順に並べる
  3. 最新のお知らせ数件を取り出す
  4. タイトル、日付、URLなど必要な項目だけ残す
  5. news-min.jsonとして出力する

11tyのJavaScriptテンプレートでは、たとえば次のように出力できます。

class LatestNewsJson {
  data() {
    return {
      permalink: "/data/news-min.json",
      eleventyExcludeFromCollections: true
    };
  }

  render(data) {
    const items = [...data.collections.news]
      .sort((a, b) => b.date - a.date)
      .slice(0, 4)
      .map((item) => ({
        title: item.data.title,
        date: item.date.toISOString().slice(0, 10),
        url: item.url
      }));

    return JSON.stringify(items);
  }
}

module.exports = LatestNewsJson;

運用時に確認したいこと

読み込み中・取得失敗時の表示

この方法では、HTMLを読み込んだ後にJavaScriptがJSONを取得します。そのため、通信や処理が完了するまでは、最新のお知らせ部分が空白になります。

記事本文の後に置く補助的な導線であれば、ページ下部へ到達するまでに取得を終えられることが多く、影響は比較的小さくなります。一方、ページ上部の重要な情報をこの方法だけで表示する構成には向きません。

JSONが見つからない、内容が壊れている、通信に失敗したといった場合は、セクションだけを非表示にします。記事本文まで読めなくならないようにすることが重要です。手順3のコードでは、この処理をcatch内で行っています。

キャッシュによる反映遅れ

S3やCDNを利用している場合は、JSONをアップロードしても古い内容がキャッシュに残ることがあります。更新後に反映されない場合は、次の点を確認します。

  • JSONファイルのキャッシュ設定
  • CDNのキャッシュ削除
  • ブラウザーキャッシュ
  • アップロード先のパス
  • JavaScriptが取得しているURL

毎回クエリ文字列を変える方法もありますが、毎回キャッシュを使わなくなるため、通常はおすすめしません。更新頻度に合わせてJSONのキャッシュ時間を短くする、公開時にCDNのキャッシュを削除するなど、サイト全体の運用に合わせて決めます。

デザイン変更時の修正範囲

カード部分を生成するcreateNewsItem()は、共通コンポーネントに近い役割を持ちます。カテゴリーや矢印を追加するなどHTML構造を変える場合も、共通JavaScriptを修正すれば全ページへ反映できます。

変更範囲は次のように整理できます。

  • 見た目だけを変える:CSS
  • カードのHTML構造を変える:JavaScript
  • 表示する情報を増やす:JSON生成処理とJavaScript

まとめ

静的サイトの各詳細ページに最新のお知らせを表示するために、すべてのHTMLを毎回更新する必要はありません。

JSONへ最新のお知らせ数件をまとめ、各ページからJavaScriptで読み込めば、更新対象を新しい詳細ページとJSONファイルに絞れます。静的サイトジェネレーターの元データからJSONを自動生成すれば、手作業による更新漏れも減らせます。

ただし、サイト全体を自動ビルド・自動公開できるなら、ビルド時にHTMLへ埋め込む方が素直です。担当者が更新する、下書きや予約公開が必要といった案件では、CMSも含めて検討します。

この方法は、制作者や制作会社が更新を担当し、CMSを導入するほどではない静的サイトで、軽さと更新性を両立しやすい構成です。

関連記事

一覧や詳細ページが不要な小さなお知らせであれば、静的サイトのお知らせ表示を作る4つの方法で紹介している方法を検討します。お知らせを担当者自身で更新したい場合も、GoogleスプレッドシートやCMSを含めて、更新する人と必要な機能から決めると整理しやすくなります。