年始の学習ログ

2022年から23年にかけて、時間があったのでWebアプリを作りはじめました。 GitHubの草、contributionsの増減を2年分見比べられるやつです。

koji-1009.github.io

github.com

経緯

年末といえば振り返りです。 例に漏れず、自分もこの数年適当にやってはブログにまとめています。

blog.dr1009.com

blog.dr1009.com

振り返りをしていると、なんとなく年を跨いで比較してみたくなります。 年度ごとのContributionsをポチポチ切り替えてもいいのですが、可能であればより詳細にグラフ化したくなりました。 ざっと調べたところ、GitHubのGraphQL APIを利用するとできそうだったので、試すことにした次第です。


普段はAndroidiOSのアプリを書いているので、KotlinやSwift、そしてDartであればいつもの流れで開発できます。 ただ、せっかく余暇にアプリを作る機会だと思ったので、TypeScriptで実装してみることにしました。 また、KotlinとAndroidの組み合わせだと、新たに経験値を積む感覚がなく。SwiftとiOSの組み合わせだと、配布して試すのが厄介。 DartとFlutterの場合、GraphQLの処理をするのがライブラリの選択肢的につらい、という理由もあることはあります。。

TypeScriptを使うとなると、気になるのがeslintやformatの設定周りです。 普段IntelliJ系 + Kotlinや、Flutterのコードをdart formatで整形していることもあり、半自動でできないと面倒です。

つらい。

deno + Fresh

ざざっと調べたところ、denoに fmt コマンドがあるとのこと。 なので、denoでやってみることにします。

deno.land

とりあえずdenoをセットアップし、ドキュメントを確認していると、Freshが紹介されていました。 よくわからないものの、むしろよくわからないものを触った方がいいだろうの精神で採用。

deno.land

fresh.deno.dev


freshの仕組みは、半日ぐらい触ってみると大体把握できます。

fresh.deno.dev

ハマった思い出としては、 islandsconsole.log はブラウザのコンソールに、routesconsole.log は端末のターミナルに表示されることです。仕組みがわかった今であれば「それはそう」という話なのですが、それが理解できるまでは「???」という感じでした。

状態管理については、シンプルな画面なので useState が利用できれば、大体問題ありませんでした。 VSCodeに関しても、型が(少し過剰なほどに)表示されることもあり、非常に利用しやすかったです。


ただ、deno + Freshの組み合わせで、アプリを開発するのが困難だと判断することになりました。 おおよその理由は、以下のとおりです。

  1. import_map.json の自動更新がうまく動かせない
  2. GraphQLを、クライアントとして利用できる仕組みが弱い
  3. chartを描画するのが難しい

GraphQLに関しては、最初はApolloを利用するつもりでした。 ただ、2022年末の時点では、下記のreactが依存に入る問題を回避し切ることが難しかったです。*1 次のメジャーリリースで解消されるとのことなので、リリースされたら簡単に利用できるかなと。これは時期が悪かったですね。

github.com

denoで利用できるライブラリを探すと、次のものが見つかります。

https://deno.land/x/graphql_request@v4.1.0

とはいえ、機能が非常にシンプルになります。 今回は、1つか2つのクエリを投げるだけになるので、fetch と自前でinterfaceを定義することで対応することとしました。3年ぐらい前に、GraphQLについて勉強しておいてよかったです。

blog.dr1009.com


今回利用したいアプリでは、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して、一旦寝かせてあります。 半年ぐらい経ったら、もう一度やってみてもいいかな……。

github.com

node + React

心機一転、nodeとReactで実装することにしました。 Freshでアプリを作るため、2日ほどTypeScriptやVSCodeをいじり回していたので、だいぶ慣れがあったので、当初より取り組みやすかったように思います。

create-react-app.dev

eslint.org

prettier.io

一つ一つ話を追っていくと、公式ドキュメントを順々に実装すれば、大半はなんとかなります。 公式以外のドキュメントを参考にしたのは、.eslintrc.jspackage.json から extends を移すところと、 parserOptions のあれこれ、 .tsx を含める設定あたりだったかなと。


GraphQL関連の実装は、思っていた以上に簡単でした。 公式ドキュメントの通り、順々に実装するだけでよかったです。 *2

www.apollographql.com

レイアウトの調整は、慣れているMaterial Designベースに。 日付に関しては、人気の高いライブラリを選ぶことにしました。

mui.com

date-fns.org

「検索の終了日」を設定するためにカレンダーを利用する必要があるのですが、 input ではなく DatePicker を利用することで、 Date 型を利用できるようになるのがありがたかったです。 この辺りは、普段使っているフレームワークと異なり、動的な型づけの雰囲気があって「お〜」ってなったところです。

mui.com

そのあとは、あれこれ試行錯誤しながらフォルダ構成をいじっていたら、アプリが出来上がっていました。よかったです。 MDのbreakpointを反映したbodyのサイズを実現するために、 useRef とか useCallback などを利用したので、結構いい勉強になったかなと思います。


公開する場所はちょっとだけ悩みましたが、ほぼ自分だけが使うだろうしということで、GitHub Pagesにしました。 簡単に公開できる仕組みがあるのは、本当にありがたいですよね〜。

まとめ

そんなこんなで、お正月を使って簡単なアプリを公開しました。 時間があるって素晴らしい。

read:user の権限が与えられている、GitHub personal access tokenがあれば動作するはずです。 *3

docs.github.com


ReactでApolloを使うと、AndroidiOSよりも簡単に開発ができることを知れたのは、大きな収穫でした。 この簡易さなら、他に欲しいな〜と思っている機能(今日対応したPRレビューの一覧とか)をリストにする機能なんかも、いつか調整んして見たいなと思います。 単純に、contributionのタイプを分類してグラフ化もしてみたいですしね。時間のある時に、APIをよく確認したいと思います。

Flutter、GraphQLがもっと使いやすくなるといいなぁ……。 isarがWebのサポートを2023年中に見込んでいるので、色々と期待の一年です。 *4

*1:issueで議論されている方法でapollo-clientの依存は解決できたのですが、そこからgqlあたりを参照させていくと、エラーが発生してしまいました。。

*2:後ほど、CLIの更新後に型定義が自動生成されなくなったりして、頭を抱えたりもするのですが……

*3:利便性のために、値をlocal storageに保存しているので、気になる方は終了後に空文字を入力するなどしてください。

*4:v2系で対応されていましたが、v3系で一時的にdropしています。詳細はissue