Remix

Remixでは副作用のためのモジュールインポートは避けた方が良い

引き続きRemixで開発していたところ、クラアント側で動作させたいコードで、副作用モジュールインポートを行っていると問題が起きることがわかりました:

import 'hoge'

上記のようなimportです。このimportを行う側のコードでは、hogeの中身を名前で参照していませんので、このimportは、hogeのロード時1度限りのコード実行を目的としたものです。

今回このhogeの中身では、グローバルオブジェクトに新しいプロパティを付け加える処理を行っています。

$ npm run dev

で開発しているときには、上記のimportを行うコードは正しく実行されていたのですが、

$ npm run build
$ npm run start

にて、ビルドした成果物を動かすと、hogeが全く動作していませんでした(hogeで付け加えられるべきプロパティが存在しなかったため、エラーが起きた)。

散々悩んだ挙げ句、Module Constraintsで説明されている通り、Remixで上記のような副作用を目的としたモジュールのimportは行わない方が良さそうです。

今回の目的では、hogeの実行はimport時ではなく、ページ初期化後でも構わなかったため、hogeの中身をexport functionとし、副作用モジュールインポートを、関数のインポートに置き換えました。そして、当該functionをuseEffectの中から呼び出すようにました。この方法は、Lazy Initializationで紹介されているものです。

動作確認したバージョン

  • @remix-run/cloudflare: 2.10.3
  • remix-utils: 7.6.0
  • react: 18.3.1

RemixでSSRをバイパスするにはremix-utilsを使おう

Remixleafletを使用する開発で、SSRフレームワーク定番(参考1, 参考2)の"window is not defined"がサーバ側の端末で表示される現象に遭遇しました。

要するに、ブラウザでのみ動かしたいコードがサーバ側のSSRで動いてしまっているわけです。

Next.jsだとdynamicで囲って対処していましたが、Remixでどうやってやるのか調べました。

Remix Viteで一部をクライアントサイドのみにするでは、ReactのlazyとSuspenseを組み合わせて行けるとのことでしたが、私が試した限りではうまくいきませんでした(やり方が悪かっただけかもしれません)。

結局、remix-utilsClientOnlyを使って解決しました。

動作確認したバージョン

  • @remix-run/cloudflare: 2.10.2
  • remix-utils: 7.6.0
  • react: 18.3.1

フロントエンド界隈は開発が活発なので、この記事の内容もあっという間に陳腐化するかもしれませんが、備忘録として残しておきます。