Remix
- 従来の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.
vitest導入
- remix viteのテンプレにvitestを導入する時、vitest用の設定ファイルとviteの設定ファイルを分けないとpluginが競合するのかうまく動作しない。
https://remix.run/docs/en/main/future/vite#plugin-usage-with-other-vite-based-tools-eg-vitest-storybook
どうやら現状、vitestとかstorybook使う時はあえてプラグインを切り替えるか、環境ごとで設定ファイルを作る必要あり
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として設定したら解決した。(最初からそうなってた)
Remix-viteとstorybook, tailwindの設定
- tailwindとstorybookの設定は以下を参照した。
- remix-viteの場合、vite.config.tsにて追加の記述が必要。
process.argvでnpm scriptsの最初のコマンド取得して、storybookコマンドだった時はremix-vite用のプラグインを含めない実装にする必要がある。
- tailwindの設定
詰まったとこ
- 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(),
], ....
-
app/routes
配下にてネストしたディレクトリ構成にしようとしたらうまくいかず。ネストしたディレクトリ構成で開発したい場合はremix-flat-routesを使う必要あり。
以下のepicStackの構成ではremix-viteに対して、remix-flat-routesを使っているので参考になる。
https://github.com/epicweb-dev/epic-stack/blob/main/package.json
https://interactive-remix-routing-v2.netlify.app/ -
RemixのAPIを使った画面のテストをする場合は
@remix-run/testing
ライブラリが必要
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を表示できる。