記事一覧から下書きのカードを消しても、詳細ページが生成されていればURLから読めます。静的サイトで公開状態を管理するには、表示するカードだけでなく、どのページを生成するかまで条件をそろえる必要があります。GENEVISのAstroサイトで使っている、記事の公開判定とページ生成の仕組みを説明します。
原稿の状態を、ページ生成の条件にする
このサイトでは、MarkdownをContent Collectionsで読み込み、記事の先頭にタイトル、slug、日付、公開状態などを置いています。必須項目と形式はスキーマで検証します。読み込みの基盤はAstroの機能で、三つの公開状態と判定規則はこのプロジェクトで定義したものです。Astro公式のContent Collectionsガイド
| 状態 | 開発・確認用 | 通常生成 |
|---|---|---|
draft | 詳細も一覧も生成しない | 生成しない |
sample | 確認用原稿として表示 | 生成しない |
published | 公開日時に達したものを表示 | 公開日時に達したものを生成 |
draftを開発中にも表示しないのは、原稿が存在することと、ページとして確認対象にすることを分けるためです。表示確認にはsampleを使い、画面にも確認用であることを出します。
publishedは生成対象の指定で、本番配置を実行する操作ではありません。ページの生成対象と、本番へ配置する作業を分けて管理しています。
一覧と詳細が、同じ対象を受け取る
公開条件はvisibleEntries()へまとめました。getEntries()がコレクションを取得してこの関数へ渡し、一覧、TOP、記事詳細の生成などが同じ対象を使います。
詳細ページのgetStaticPaths()でも、取得した全原稿から直接パスを作らず、公開条件を通った記事から生成します。そうすることで、一覧にはない下書きの詳細ページだけが残る状態を避けます。
判定関数は現在時刻を引数で渡せるため、テストで時刻を固定できます。未来の公開日を使ったテストが、日付の経過で突然失敗することを避け、境界条件も再現しやすくします。
表示順は、使う場所ごとの規則で決めています。visibleEntries()の基本順序は、注目指定、公開日の降順、slugの順です。BLOG一覧とTOPの新着記事では、getBlogArticles()で注目指定にかかわらず公開日の新しい順へ並べ直します。サービスページの記事は対応する領域と優先指定、関連記事は記事側の指定順を使います。
確認用のページと、XMLサイトマップを分ける
確認用生成ではsampleの詳細ページを作りますが、検索エンジン向けのXMLサイトマップには含めません。XMLサイトマップの生成では、確認用モードでも通常公開と同じ条件を使います。
確認用のBLOG一覧にはsampleの記事を含めます。閲覧用サイトマップは主要ページへの入口をまとめるもので、記事詳細は列挙しません。記事単位の公開対象は、BLOG一覧とXMLサイトマップで確認します。
確認用のHTMLが生成される以上、その生成物を外部へ配置すればURLから読めます。noindexやサイトマップへの非掲載は閲覧制限にはなりません。原稿の公開判定と、確認用環境へのアクセス制御は別の責務です。
静的サイトの公開日は、時刻だけでページを変えない
通常生成では、publishedAtが判定時刻以前の原稿を対象にしています。しかし、一度生成して配置したHTMLは、その後に公開日時が来ても自動で増えません。記事を反映するには、その時点での再ビルドと配置が必要です。
日付だけを書く場合の時刻の扱いにも注意が必要です。この実装では日付をJavaScriptのDateへ変換しています。日付だけの指定を「日本時間のその日0時に必ず公開する機能」としては扱っていません。時刻指定の運用が必要になれば、タイムゾーンと実行スケジュールを合わせて設計します。
これは予約記事に限らず、公開済みの記事を下書きへ戻す場合も同じです。原稿の状態変更に加えて、生成物を更新し、公開先へ以前の詳細ページが残らないようにする必要があります。ここで説明しているのはローカルでの生成と検証の範囲です。本番の配置・削除運用の検証は含みません。
非表示の原稿も、重複検証の対象にする
slugの重複は、非表示の記事を除く前に検出します。下書きだから今は問題にならないとして残すと、公開へ切り替えた段階で既存記事とURLが衝突する可能性があるためです。
関連記事の参照でも、存在する非表示記事と、存在しない記事を区別します。原稿があっても公開条件を満たさなければリンクは出さず、参照先自体が存在しなければ設定誤りとして検出します。
既存テストでは、下書き・サンプル・未来記事の分離、URL重複、表示順を確認しています。生成物の検証では、リンク先、アンカー、H1、ID重複などを調べます。関数の判定と、実際にできたHTMLの両方を見ることで、設定が正しいだけでは気づけない食い違いも探します。
状態と確認範囲を分けたほかの実装記録には、Three.jsの背景演出の停止・再開・障害時表示があります。記事管理とは対象が違いますが、通常時以外の条件も明示して検証する例です。
公開状態を一か所で決め、その結果をページ生成まで通すこと。そのうえで、生成したものをどの環境へ置くかを区別すること。この二段階を分けておくと、記事が増えても確認用と公開用の扱いを追いやすくなります。