クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【React/Next.js】大戦国・年表を作った(年表は随時追加中ー)

前回つくった「ビートルズDB」をベースにして「大戦国・年表」もつくりました。これによってNext.jsの動的ページの詳細設定やスプレッドシートでの重複チェックの知見が増えました。大戦国・年表は南北合一から元和偃武までの戦国時代(1392〜1616年)の年表を作っていくプロジェクトです(年表は随時追加中)。それではいきましょう!

【目次】

※参考:前回記事
【React/Next.js】「ビートルズDB」を作った(ビートルズの楽曲を検索できるアプリ) - クモのようにコツコツと

※参考:【React】ReactでWebアプリを作るシリーズまとめ
qiita.com

作ったもの

大戦国・年表トップページ

※参考:大戦国・年表


出来事ページ

※参考:桶狭間の戦い


ソースコード

※参考:GitHub - ryo-i/dai-sengoku-nenpyo


前回作成した「ビートルズDB」をベースにしており、その戦国時代版となるアプリ

※参考:ビートルズDB

なぜこのアプリを作ったのか

自分は戦国時代が好きで小学校の頃から戦国時代の本を愛読してきた。

頭の中に戦国時代の知識は積み重ねられているが、それらの点と点が繋がらず、曖昧になっている。

  • ○○の戦いと○○の戦いはどっちが先だったっけ?
  • ○○○○は○○の戦いに参加していたっけ?
  • ○○の戦いの頃の将軍って誰だっけ?

点在した情報を統一フォーマットでデータ化し、時代、地域、人物など、いろいろな切り口で絞り込みが行えると便利だと思った。

なお、時代はどこからどこまで扱うか悩んだが(戦国時代の期間がいつからいつまでか、も諸説ある)、いっそのこと一番広い範囲として南北朝合一(明徳の和約)から元和偃武(家康の死亡)まで、1392〜1616年を扱うことにした。

このアプリで経験しこと

スプシの値の重複チェック

ビートルズDBの時は曲がこれ以上増えないため、曲に連番のid番号を振って動的パスした。

大戦国・年表では出来事を増やしていくので番号を振る運用は向かない。出来事のタイトルをそのまま動的なパスにしたいが、そうすると「川中島の戦い」など複数件同じタイトルがあるとうまく動かなそう。

※参考:dai-sengoku-nenpyo/[path].tsx at main · ryo-i/dai-sengoku-nenpyo · GitHub


スプシ使いの弟から教えてもらったノウハウ

項目 方法
キーの生成 &でつなげるだけ。text()を使うと、数値の場合に桁を揃えたりできる。
重複チェック① countifを使うと、重複数を数値で出せたりする。
重複チェック② 条件付き書式でcountifの結果が2以上だと色がつくようにできる。
重複チェック③ countif列の計算式を手で貼り付ける必要はある。
青字・赤字① 年や年号の切替をoffset関数で値として表現。(offsetは相対的な処理をしてくれる。)
青字・赤字② その値と西暦や和暦のカテゴリを参照して条件付き書式を設定。
別表からの呼び出し① index+matchを使うと、キーに該当する値を持ってくることができる。(vlookupでもOK。)
別表からの呼び出し② 複数のキーで呼び出したい場合は、&でつなげると可能。
  • 条件付き書式は上の方が優先度が高い
  • $マークは計算式を貼り付けたり、条件付き書式の動作のときに列や行を固定する(縛る)動きをしてくれる。

天皇家や将軍などの権力者は別シートにまとめて、indexとmatchを組み合わせて出来事の年から引っ張ってくるようにした! これで固有な内容の入力に集中できる♪

=index(authority!I:I,match($B2&$C2&$J2&$K2,authority!$B:$B&authority!$C:$C&authority!$E:$E&authority!$F:$F,0),1)

※参考:COUNTIF関数
表内の重複するデータを取り除きたい! COUNTIF関数でダブりを発見・UNIQUE関数でクリーンな表を作る方法 - 窓の杜

※参考:INDEX、MATCH関数 スプレッドシートのINDEX、MATCH関数で簡易検索を実装


その他、スプシ関係でやったことはこちらのイシューに記録している

※参考:戦国年表作成 · Issue #2 · ryo-i/dai-sengoku-nenpyo · GitHub

getStaticPropsの再レンダリング

新規で追加したページが404になることがあり、そういうページは年表一覧でもリンク取得が404になっている。Local環境では起こらないが本番環境で起こる。

いろいろ調べて試した結果、下記の方法でうまくいったっぽい。


fallbackとnotFoundを組み合わせてgetStaticPropsのパスの取得終わったら再レンダリング

// Get Path
export async function getStaticPaths() {
    const res = await fetch(`https://dai-sengoku-nenpyo.vercel.app/api/nenpyo/nenpyolist`);
    const event = await res.json();
    // console.log('event', event);

    const paths = event.nenpyoList.map((data) => `/event/${data.path}`);
    // console.log('paths', paths);
    return {
        paths,
        fallback: 'blocking'
    };
}

※参考:Next.js の SSG で 404 ページを適切に表示する ++ Gaji-Laboブログ


  • getStaticPropsにrevalidate: 10を追加(10秒たったら更新)
  • getStaticPathsのfallbackをblockingに

Next.jsのISRで動的コンテンツをキャッシュするときの戦略

export async function getStaticProps({ params }) {
    const path = params.path;
    const eventInfo = {
        path: ''
      };
      eventInfo.path = path;

    // console.log('path', path);
    // console.log('pathInfo', eventInfo);
    return {
        props: {
            eventInfo
        },
        notFound: !eventInfo,
        revalidate: 10
    };
}

※参考:Next.jsのISRで動的コンテンツをキャッシュするときの戦略

※参考:ソースコード
dai-sengoku-nenpyo/[path].tsx at main · ryo-i/dai-sengoku-nenpyo · GitHub


その他、つまづいたこと、試したことなどこちらのイシューに記録している

※参考:年表をページ上に表示する · Issue #3 · ryo-i/dai-sengoku-nenpyo · GitHub

参考サイト・参考文献

今回のアプリを作ることで西暦と和暦には誤差があることを知った。12月頃に改元した元号は西暦がズレる。また、西暦も1582年からグレゴリオ歴からユリウス暦に変わっていた。特に、和暦と西暦の変換が調べられる「高精度計算サイト」サイトに助けられた。

※参考:和暦・西暦
元号一覧 (日本) - Wikipedia
生活や実務に役立つ高精度計算サイト
西暦カレンダー変換 - 高精度計算サイト


場所は基本的に律令国だが、東北は広いため、明治初頭に分割された新たな律令国にした。特に陸前・陸中あたりは入り組んでわかりにくかったが、律令国を郡単位で掲載されている「府県の変遷」サイトに助けられた。

※参考:律令国
令制国一覧 - Wikipedia
http://www.tt.rim.or.jp/~ishato/tiri/gun/map/1871/26tyuo.htm
http://www.tt.rim.or.jp/~ishato/tiri/gun/map/1871/27hokuo.htm
http://www.tt.rim.or.jp/~ishato/tiri/gun/map/1871/28ryou.htm


天皇、関白、将軍、管領などの情報はWikipediaに細かく記載されており、助けられた。特に関白は再任が多くてわかりずらく、とても参考になった。

天皇の一覧 - Wikipedia
摂政・関白の一覧 - Wikipedia
足利将軍一覧 - Wikipedia
徳川将軍一覧 - Wikipedia


その他、イイダリョウが小学生時代から集めてきた戦国時代の本(今後、年表に反映させていく予定)

※参考:参考文献 | 大戦国・年表

最後に

ということで「大戦国・年表」の枠組み的な部分が出来上がりました。

あとは年表の内容をどんどん充実させていくのみです!これはもう気長に少しずつ取り組んでいきます。生きている間に終わればいいな。ライフワーク…。

さて、データベース系はいったんここで一区切りにして、これからはNext.js + Three.jsのコンテンツをメインにしていきたく思います。それではまた!