Open6

Remix

m_03m_03
  • 従来のreactフレームワークでは、サーバーのデータをフロントでステートとして管理して、それをUIに表示するという、ある種二重のデータ管理が行われていたが、Remixではフロントからサーバーのデータに対して直接actionを実行し、サーバーの値をステートとしてUIを変更するという、シンプルな形になっている。
  • web標準に忠実で内部的にはブラウザの標準APIが使われている。
  • プロジェクトテンプレート
    https://remix.run/resources?category=templates
  • remixのクラシックコンパイラよりviteの方がいいらしい。今後viteを標準にするらしいので、viteのプロジェクトを使う。
    https://remix.run/docs/en/main/future/vite
  • 内部的にreact-router使われてる
  • ファイル名でのルーティングガイド
    https://remix.run/docs/en/main/file-conventions/routes
  • ファイル内にloader関数を定義して、内部でデータフェッチ処理、そのファイルのエクスポートしているコンポーネント内でuseLoaderDataを使ってデータ取得。
  • Formタグはサーバーへのデータ送信はせず、fetchAPIを使ってaction関数にリクエストを送信するらしい。actionが完了したら、ページを再検証する。remixがフォームデータ変換してサーバーにリクエストを送るのではなく、ブラウザがフォームデータを変換してサーバーにドキュメントリクエストを行うらしい。

This is where the "old school web" programming model shows up. <Form> prevents the browser from sending the request to the server and sends it to your route's action function instead with fetch.
In web semantics, a POST usually means some data is changing. By convention, Remix uses this as a hint to automatically revalidate the data on the page after the action finishes.
In fact, since it's all just HTML and HTTP, you could disable JavaScript and the whole thing will still work. Instead of Remix serializing the form and making a fetch request to your server, the browser will serialize the form and make a document request. From there Remix will render the page server side and send it down. It's the same UI in the end either way.
We'll keep JavaScript around though because we're going to make a better user experience than spinning favicons and static documents.

m_03m_03

remix-viteでeslintの設定ファイルの拡張子をjsにしたら読み込めない

  • eslintの拡張子を.jsとして作成したけどうまく読み込めない
  • remix-viteのpackage.jsonはtypeがmoduleになっているのでESMの設定となっており、.js=.mjsとして扱われている。
  • eslintの最新ドキュメント読んだらeslintはESM形式に対応していないらしいので、type:"module"の時は、拡張子はcjsにしてくれとのこと。

JavaScript (ESM) - use .eslintrc.cjs when running ESLint in JavaScript packages that specify "type":"module" in their package.json. Note that ESLint does not support ESM configuration at this time.

cjsとして設定したら解決した。(最初からそうなってた)

m_03m_03

Remix-viteとstorybook, tailwindの設定

  • tailwindとstorybookの設定は以下を参照した。

https://zenn.dev/t_tonyo_maru/articles/0d88102e489725

  • remix-viteの場合、vite.config.tsにて追加の記述が必要。

https://remix.run/docs/en/main/future/vite#plugin-usage-with-other-vite-based-tools-eg-vitest-storybook

process.argvでnpm scriptsの最初のコマンド取得して、storybookコマンドだった時はremix-vite用のプラグインを含めない実装にする必要がある。

  • tailwindの設定

https://tailwindcss.com/docs/guides/remix

m_03m_03

詰まったとこ

  • app/routeは以下のindex.tsxはアンダースコア付きにしないといけない。_index.tsxでないと、トップページとして認識してくれない。
  • テストファイルをapp/routes配下に配置すると、以下のエラーが発生。

Vitest failed to access its internal state.
One of the following is possible:
"vitest" is imported directly without running "vitest" command
"vitest" is imported inside "globalSetup"

remix-viteを使ったプロジェクトの場合、vite.config.tsにてプラグインを読み込ませる必要があるが、そのプラグインの設定でテストファイルを無視する設定を書く必要がある。

export default defineConfig({
  plugins: [
    !process.env.VITEST && !isStorybook
      ? remixVitePlugin({
          ignoredRouteFiles: [
           // testファイルを無視
            '**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}',
           // cssファイルを無視
            '**/*.css',
          ],
        })
      : react(),
    tsconfigPaths(),
  ], ....

https://remix.run/docs/en/main/other-api/testing

m_03m_03

defer

例えば、いくつかのデータを複数のソースから取得してUIに返す場合、先に表示したいデータと、取得に時間がかかるので後回し表示でも良いデータがある場合などに使える。
loader関数の中でリターンする際にdeferを使う。

export async function loader (){
  const quickData = await getQuickData() 
  const slowData =  getSlowData()
return defer({ quickData, slowData })
}

こうすれば、UI側でSuspenseとAwaitタグを使ってquickDataを先に表示しつつ、slowDataに対してfallbackのUIを表示できる。

https://remix.run/docs/en/main/guides/streaming#3-deferring-data-in-loaders