2022年から23年にかけて、時間があったのでWebアプリを作りはじめました。 GitHubの草、contributionsの増減を2年分見比べられるやつです。
経緯
年末といえば振り返りです。 例に漏れず、自分もこの数年適当にやってはブログにまとめています。
振り返りをしていると、なんとなく年を跨いで比較してみたくなります。 年度ごとのContributionsをポチポチ切り替えてもいいのですが、可能であればより詳細にグラフ化したくなりました。 ざっと調べたところ、GitHubのGraphQL APIを利用するとできそうだったので、試すことにした次第です。
普段はAndroidやiOSのアプリを書いているので、KotlinやSwift、そしてDartであればいつもの流れで開発できます。 ただ、せっかく余暇にアプリを作る機会だと思ったので、TypeScriptで実装してみることにしました。 また、KotlinとAndroidの組み合わせだと、新たに経験値を積む感覚がなく。SwiftとiOSの組み合わせだと、配布して試すのが厄介。 DartとFlutterの場合、GraphQLの処理をするのがライブラリの選択肢的につらい、という理由もあることはあります。。
TypeScriptを使うとなると、気になるのがeslintやformatの設定周りです。
普段IntelliJ系 + Kotlinや、Flutterのコードをdart format
で整形していることもあり、半自動でできないと面倒です。
ReactでWebアプリ作りたいって気持ちがあるんだけれど、TSを含めてテンプレート作成するあたりまではキャッチアップしなおしたものの、eslintとprettierがいまいちわからんってところで足踏みしてる。
— Koji Wakamiya(だぐりば) (@D_R_1009) December 31, 2022
eslintでtsxのimport順を揃えたいだけのアレがめんどくさすぎて心折れかけてる。
— Koji Wakamiya(だぐりば) (@D_R_1009) December 31, 2022
つらい。
deno + Fresh
ざざっと調べたところ、denoに fmt
コマンドがあるとのこと。
なので、denoでやってみることにします。
とりあえずdenoをセットアップし、ドキュメントを確認していると、Freshが紹介されていました。 よくわからないものの、むしろよくわからないものを触った方がいいだろうの精神で採用。
freshの仕組みは、半日ぐらい触ってみると大体把握できます。
ハマった思い出としては、 islands
の console.log
はブラウザのコンソールに、routes
の console.log
は端末のターミナルに表示されることです。仕組みがわかった今であれば「それはそう」という話なのですが、それが理解できるまでは「???」という感じでした。
状態管理については、シンプルな画面なので useState
が利用できれば、大体問題ありませんでした。
VSCodeに関しても、型が(少し過剰なほどに)表示されることもあり、非常に利用しやすかったです。
ただ、deno + Freshの組み合わせで、アプリを開発するのが困難だと判断することになりました。 おおよその理由は、以下のとおりです。
import_map.json
の自動更新がうまく動かせない- GraphQLを、クライアントとして利用できる仕組みが弱い
- chartを描画するのが難しい
GraphQLに関しては、最初はApolloを利用するつもりでした。
ただ、2022年末の時点では、下記のreact
が依存に入る問題を回避し切ることが難しかったです。*1
次のメジャーリリースで解消されるとのことなので、リリースされたら簡単に利用できるかなと。これは時期が悪かったですね。
denoで利用できるライブラリを探すと、次のものが見つかります。
https://deno.land/x/graphql_request@v4.1.0
とはいえ、機能が非常にシンプルになります。
今回は、1つか2つのクエリを投げるだけになるので、fetch
と自前でinterfaceを定義することで対応することとしました。3年ぐらい前に、GraphQLについて勉強しておいてよかったです。
今回利用したいアプリでは、chartを描画することが必須となります。 このため、chartjsをfreshで利用できないか調べました。
https://deno.land/x/fresh_charts@0.2.1
ざっと調べる限り、chartjsをラップしているのは、こちらのライブラリです。
ただ、内部的にnodeへの依存をもっているため、 island
で利用(ブラウザ側で利用)することができませんでした。
ライブラリのドキュメントに
A server side rendered charting library for Fresh based on Chart.js.
と書いてあるので、そういうもののようです。 おそらく、アプリ内で「データをリクエストすると、チャートの画像を返す」pathをつくれば、この問題は解決するように思います。ただ、今回のアプリケーションでは画像ではなくチャートを表示したかったので、断念することとにしました。 chartjsを描画させてみようかと思ったのですが、canvasをいじる必要があるので、パパッと実装できなかったです。くやしい。。
だいたい、ここまでが22年12月31日から、23年1月1日の試行錯誤です。 この辺で「できなくはないだろうけど、他の道を取った方がいいかも」と思い出しました。 一応、お正月中に終わらせたいですしね。
GitHubにpushして、一旦寝かせてあります。 半年ぐらい経ったら、もう一度やってみてもいいかな……。
node + React
心機一転、nodeとReactで実装することにしました。 Freshでアプリを作るため、2日ほどTypeScriptやVSCodeをいじり回していたので、だいぶ慣れがあったので、当初より取り組みやすかったように思います。
一つ一つ話を追っていくと、公式ドキュメントを順々に実装すれば、大半はなんとかなります。
公式以外のドキュメントを参考にしたのは、.eslintrc.js
に package.json
から extends
を移すところと、 parserOptions
のあれこれ、 .tsx
を含める設定あたりだったかなと。
GraphQL関連の実装は、思っていた以上に簡単でした。 公式ドキュメントの通り、順々に実装するだけでよかったです。 *2
レイアウトの調整は、慣れているMaterial Designベースに。 日付に関しては、人気の高いライブラリを選ぶことにしました。
「検索の終了日」を設定するためにカレンダーを利用する必要があるのですが、 input
ではなく DatePicker
を利用することで、 Date
型を利用できるようになるのがありがたかったです。
この辺りは、普段使っているフレームワークと異なり、動的な型づけの雰囲気があって「お〜」ってなったところです。
そのあとは、あれこれ試行錯誤しながらフォルダ構成をいじっていたら、アプリが出来上がっていました。よかったです。
MDのbreakpointを反映したbodyのサイズを実現するために、 useRef
とか useCallback
などを利用したので、結構いい勉強になったかなと思います。
公開する場所はちょっとだけ悩みましたが、ほぼ自分だけが使うだろうしということで、GitHub Pagesにしました。 簡単に公開できる仕組みがあるのは、本当にありがたいですよね〜。
まとめ
そんなこんなで、お正月を使って簡単なアプリを公開しました。 時間があるって素晴らしい。
read:user
の権限が与えられている、GitHub personal access tokenがあれば動作するはずです。
*3
ReactでApolloを使うと、AndroidやiOSよりも簡単に開発ができることを知れたのは、大きな収穫でした。 この簡易さなら、他に欲しいな〜と思っている機能(今日対応したPRレビューの一覧とか)をリストにする機能なんかも、いつか調整んして見たいなと思います。 単純に、contributionのタイプを分類してグラフ化もしてみたいですしね。時間のある時に、APIをよく確認したいと思います。
Flutter、GraphQLがもっと使いやすくなるといいなぁ……。 isarがWebのサポートを2023年中に見込んでいるので、色々と期待の一年です。 *4