#91 Remixのjson()に泣く ─ 個人開発者向けのサービスの開発記録

tyshgc
·

本日の(5/8)の作業

Remix捨ててNext.jsに戻ろうかと思ったくらい全く原因不明な問題にぶつかったり免許更新だったりでその対応に数日費やしてしまいました。

日報が単なるRemixなどの苦労日記になってきている。。そして具体的なところでは何も進捗していない。

  • Remixが突如ビルドなどできなくなった件対応

  • 🚴 日報・分報の画面設計・実装

    • 🚴 設計・デザイン

    • 🚴 実装

  • サインインの実装

    • 認証画面実装

    • 認証ロジック実装(主にClient側)

    • Server側の認証チェック実装

    • Client側の認証チェック実装

Remixのjson()問題

まず何が起こったかの前に要件をまとめました。

  • RemixでAPI Routeを実装したい

    • API Route内でloader/actionを用意する

  • 開発環境はTurborepoによるmonorepo環境でapp, packagesと大きく区分しており、UI(/packages/ui)やドメインロジック(/packages/domains)とし、Remixは/apps/app1, /apps/app2 といった感じでアプリケーションを複数用意している

  • API Routeはapps以下それぞれのアプリケーションのroutes/以下の各種ルートファイルに定義しなければならない

  • loaderやactionのデータのやり取りはRemixではuseLoaderData HooksやuseActionData Hooksを使う。下の例の様にloader/actionそれぞれをhooksのジェネリクスに指定するとJsonifyObject型としてHooksにjson()で返した値が渡ってくる。

  • FormコンポーネントはFeature-Sliced Designのルールに則りentittiesに集約している。ここにドメイン層と結合するための独自のHooksを用意しているので、action(やloader)のhooksをこのHooks内に織り交ぜたい。

要件をまとめると「ドメイン層と結合するための独自のHooksにloaderやactionをtypeofしてuseLoaderDataやuseActionDataのジェネリクスで渡したい」となります。

このために、loader/actionの処理をpackages/domainsのgateway層に別のファイルとして置きます。treeで表現するとこんな感じ。

domains/gateways/api/fugaのloaderやactionはapp1やapp2のroutesは勿論のこと、ui/entitites/fuga/hooksのuseDomain Hooks内のuseActionDataやuseLoaderDataのジェネリクスとしても使いたい。

ここで問題なのがaction内にあるjson()さん。こいつ、内部的にはprocess(環境変数)を使って処理しているらしく、client側でうっかりimportするとこんな感じのエラーをブラウザのコンソールで吐き出します。

つまり、buildは通るのでbuildの際にはわからず、実行して初めてわかる。しかもエラーを見てもどこに原因があるか特定しにくい…。

appsのroutesの方でimportするとRemixが良しなにserverとclientでバンドルを分けるぽいのでエラーは起きないが、routesの外に持ってくるとこうなります。

このjson()が原因ということを追求するために真っさらなRemixを用意してちょっとづつコードを追加していって気づきました。serverサイドのものをclientサイドで使えばサーってこうやって見ればわかるけどさー。

ただ、原因がわかっても要件は満たせていないわけです。

が、どちらにしてもこのjson()でuseActionDataなどのHooksからデータを得たとしてもJsonifyObject型になるためSerializeする必要があり面倒くさい。その辺を解決するために「remix-typedjson」というライブラリがあります。

なんと、これに置き換えたところclientサイドでも問題なく動作しました。一つ気になるのはuseLoaderData/useActionDataではなくuseTypedLoaderData/useTypedActionData Hooksを使わなければならないので何かRemix側で破壊的な変更がアプデされた際のリスクがあります。

尚、useFetcherも活用しまくっている場合でもuseTypedFetcherというのがあるので一応は安心です。

その他、メモなど

Remix辛い

Remix、Next.jsに比べてハマり度が高い。わかってしまえば大した問題ではないけど、いかんせんviteをビルダーに採用した辺りからドキュメントが一部古かったり不十分だったり、ググっても古い情報が出てきたり、ChatGPTに聞いてもvite版までの知識がないためにあさってな回答だし、聞ける人もいないし。自分史上3番目くらいに厄介になってきている(ちなみに1位は2017年頃のReact Native)。

免許更新

うっかり2年前に高速でスピード違反で捕まってしまったので2時間の講習でした。GW中だからか人は少なく講習以外はサクサクと進んだので2時間半弱で全部終わったけど、講習は教壇に立つ担当者の明らかに時間伸ばす無駄な話(帰りは手前の階段から降りたほうが早く出口に出れるとか)に流石に時間の無駄使いされてる感で若干イラッと。

ていうかあの人たちはどういうモチベーションであの仕事をしているのだろうか?自分だったら発狂しそう。

← #90 

@tyshgc
デザインファーム及びスタートアップ(上場)などを経てフリーランスとして、様々なスタートアップや大手企業の新規事業の立ち上げ期における事業設計・アプリケーションの設計・開発、サービスのUX分析とデザインとエンジニアリングの両軸でお手伝いさせていただいています。 現在、個人開発者向けの支援サービスを個人開発中。 X Account: @tyshgc