見出し画像

Nuxt3Betaで企画乗車券データの可視化ツールを作ってみた

この記事は、NAVITIME JAPAN Advent Calendar 2021の 10日目の記事です。

今回のお話

みなさん!企画乗車券をご存知でしょうか?私は存じ上げておりますが、まだ使ったことはございません。考えるの人と申します。
昨年のAdventCalendarでは以下のような事を書いていましたが、今年は技術寄りの記事を執筆しようと思います。

さて、企画乗車券とは公共交通機関などによって販売されているもので、利用できるエリアや期間が指定されている代わりに、普通にきっぷを購入して乗車するより安く済むなどの利点がある乗車券です。
有名どころである「青春18きっぷ」や、訪日外国人旅行者向けの「Tokyo Subway Ticket」「JAPAN RAIL PASS」、特定のテーマパークの入場券付きの往復乗車券なども該当し、弊社では 2021年12月1日 現在、100件以上の企画乗車券データを取り扱っています。

私が所属するチームでは、企画乗車券の情報をサービス上で活用するためにデータの作成・運用を行っておりますが、このデータを可視化できるツールを作りたいと考えていました。

本記事では、解決したかった課題の紹介と、ツールを実現するために利用した Beta版 Nuxt3 の技術要素の紹介とを行います。

注意:Beta版の状態での利用をしているので、本リリース版とは大きく異なる場合があります。

想定する読者

  • Nuxt3 (ルーティング、コンポーネント、データフェッチ等) どんな感じか知りたい人 → Nuxt3の技術要素 見出しをご覧ください

  • 小規模なツールを作ってみようと思う人

  • 課題を解決していく過程を知るのが好きな人

書かなかったこと

  • 各要素には触れていますが、コードを用いた解説などは充実していません

  • 「Nuxt2→Nuxt3で出来るようになった事」という観点は持ち合わせていません

筆者について

  • 業務上はサーバーサイド・経路探索エンジンの開発運用

  • 社内ツールの作成レベルで React(+Redux), angular, jQuery, Vue3 などの利用経験あり

  • フロント側でのサービス開発経験や、Nuxt2 や Vue2 の経験は無し

なぜ作りたいのか

管理する企画乗車券データの中に、IDが羅列されている箇所があります。関連データの更新などにより調査が必要となるケースが一定数発生するにも関わらず、人間が読んで理解することが難しいという側面がありました。
ここをサポート出来ないか考えていたのと、Nuxt3のBeta公開の話を見たのとを経て、新しいフレームワークの学習を兼ねて(むしろこちらがメイン)、可視化ツールの作成に挑戦しようと至りました。

実現したいこと

実現にあたり、以下の項目を要件として定義しました。

  • ①定義した企画乗車券名称で絞り込みできること

  • ②路線に紐づく駅一覧を分かりやすく出力できること

  • ③駅一覧の出力のために必要な情報は、社内共通APIにリクエストして取得するため、全件まとめて表示しない

    • 利用可能な路線が1,000を超えている企画乗車券が存在するため、全件取得しようとしてAPIサーバーを輻輳させないようにする

一般的には機能要件が決まった後にフレームワーク選定をする流れがきれいですが、今回ここは気にしないことにします。

データ構造

今回、対象とするデータを概略すると、企画乗車券情報 → 公共交通機関情報 → 路線情報 → 駅リスト のように4階層のデータとなっています。

各情報の包含関係

データは企画乗車券情報の配列からなっていて、企画乗車券情報以下は下記の項目を保有しています。

データの構成

このとき一番内側にあたる駅ID配列の部分が、パッと見ただけで理解できない箇所になっていて、うまく可視化したい課題の部分となっています。

課題の箇所

Nuxt3の技術要素

ここで、機能を実現するために Nuxt3 で出来そうな事を見ていきましょう。

Getting started

公式ドキュメント

毎度お世話になる、始め方についての記述ですね。
以下のコマンドで新規プロジェクトの立ち上げができました。

npx nuxi init プロジェクト名

できたディレクトリの中身を見ると、動作に必要なファイル群が生成されています。そのまま yarn install で必要なモジュールを取得し、 yarn dev で実行することで、ブラウザ上で動作が確認出来ました。

Data Fetching

公式ドキュメント

<script setup> タグ内に記載することで、対象コンポーネントの読み込み時にリクエストの発行を行い、データ取得できました。リクエスト先としては https から始まるようなURLはもちろん、後述する server/api ディレクトリに配置するAPIも指定できました。

pages と ルーティング

公式ドキュメント

ルーティングを行いたいときに利用するものです。
app.vueファイルに <NuxtPage/> タグを追加することで、 pages 下に配置したページを表示する事ができました。
pages下の配置した名称のとおりのパスでアクセスできるようになるため、例えば pages/hoge/fuga/index.vue ファイルを作成すると、 https://ドメイン/hoge/fuga/ でアクセスできるようになります。

また、公式ドキュメントでは  Dynamic Routes と表現しているように、任意の名称を実行時に埋め込むことも出来るようです。これを利用すると、アイテムを一覧表示する親ページから、個別のアイテムを詳細表示する子ページへの遷移を実現できそうですね。

一覧表示→詳細ページの構成

私が実施したときは、 ドキュメントのExample にあるような、 group, id の構成は上手に活用できなかったので、 mountains ディレクトリを作成し、直下に [...slug].vue という名称のファイルを作成したところ、上記のようなルーティング処理を書けました。

今回作成するツールでも企画乗車券ごとにルーティングするなどできそうですが、そこまでするほどでも無いと思ったので活用しませんでした。

components

公式ドキュメント

Vue を学習する上で必ずといっていいほど出てくるコンポーネントを格納するディレクトリです。

挙動の理解はあまり深くできていないのですが、配置したコンポーネントに対応するimport文をわざわざ書かなくても、pages内のvueファイルから参照できるようになっていました。少しだけ楽をする事ができますね。

今回は、要件②の駅一覧の表示部分をコンポーネントとして定義する使い方をしました。路線を選択したら、紐づく駅一覧コンポーネントを表示するようにし、そのタイミングでリクエストを発行して駅一覧を取得できるようにしています。

composables

公式ドキュメント

複数のコンポーネントから共通で利用される関数などを、コンポーネントから切り離して記述する事ができます。上記の項目と同様に、対応するimport文をわざわざ書かなくても自動でインポートされます。
業務ロジックなどを手軽に分離・利用出来そうですね。

ただし、何でも分離して良いというわけではなく、注意して利用する必要がありそうでした。
私はここに、useFetch などNuxtで利用できるものを分離しようとしましたが、この使い方はいまいちでした。computedで定義した構文内部のように、 useFetch を利用できない箇所から呼び出したときに実行時エラーとなってしまい、原因の調査に少し悩んだ事がありました。

今回のような小規模のプロジェクトでは、活躍の場は少なそうです。

server

公式ドキュメント

ここに格納したコードは、1. apiディレクトリ下はそのままAPIのエンドポイントとして動作し、2. middlewareディレクトリ下はリクエストに作用するミドルウェア層として動作します。いわゆるサーバサイドレンダリングを実現するものと捉えています。

今回のツールでは、要件③で社内共通APIへリクエストを発行しますが、サービス上で表示しやすくするために、API層である程度整形して返却するような設計にしました。

その他(スタイリング/コンポーネントライブラリ)

Nuxt3はVue3がベースとなっています。
Vue3でも利用できるUI系ライブラリを探し、 PrimeVue を選びました。 同時に PrimeIcons, PrimeFlex も導入しています。導入にあたっては、以下の項目の実施をしました。

  • yarn経由でライブラリを追加

  • plugins/primevue-plugin.js ファイル作成、利用コンポーネントの登録

  • nuxt.config.ts ファイルに対してcss記述追加

要件①を実現するために、Listboxコンポーネントが有用でした。
また、要件③における駅一覧の表示/非表示の切り替えは、Inplaceコンポーネントで実現しました。

完成

細かい作成過程は省きますが、最終的にこんな感じになりました。

各要件がどのように実現されたか

管理しているJSONデータを貼付する部分と、データに含まれる企画乗車券情報の一覧表示ができていて、そして一覧から企画乗車券情報を選択すると下部に定義内容が出力されるようになっています。

企画乗車券情報の表示部は、複数あるID(企画乗車券通し番号、公共交通機関ID、路線ID、駅ID)を混同しないように色の濃淡を分けていて、その濃淡によって包含関係を表現してみました。

課題となっていた駅ID配列の可視化部分については、定義されている3種類とAPIサーバから取得した合計4点の配列情報を、うまく組み合わせられました。取得した駅一覧情報をベースとして、上下方向をそれぞれ「←」「→」の表示有無で表現し、乗降可能かどうかは駅名の濃淡で表現しました。

乗降可能駅・出発可能駅の表現

今後の展望としては、ツール上で操作した内容をJSON形式で出力できるようにして、ただの可視化ツールではなくエディターとして活用していきたいところですね!

さいごに

いかがだったでしょうか。

今回、管理する企画乗車券データの課題についてお話しました。課題の解決方法は今回挙げたもの以外にも色々ありますが、今回はブラウザ上で操作できるツールを作成することで解決してみました。早速調査などでも利用する機会があり、作ってよかったなと実感しています。

本題とは逸れますが、企画乗車券データがサービス上でどのように活用されているかについては、3日目の記事で少し触れているので、ご興味がありましたらこちらもご覧ください。

Nuxt3の使用感としては、Vue3をそのまま使う事に比べると省略できるコードが多く、規模の小さいツールの作成において有力そうな手段だなと感じました。もちろん、大規模なサービスでの活用においても、アトミックデザインに応じたディレクトリ構成にするなど適切なルール決めがあれば、十二分に力を発揮してくれそうです。

今後、利用者が増えていってドキュメントが充実していくといいなと思いつつ、本記事も(あまり詳細書いていないですが)その一員となれていたら嬉しいです。