React Server Components w/ Next.js 現状
Next.js v12.0.8-canary.12 での検証
canary.13でキャッシュのパージをするようになったがそれで無限ループを起こしている
面倒で報告できてない
Context APIが使えないのでuseRouter/withRouterが使えない(React Server Components)
pages/_app.tsxにそれっぽいやつが降ってくるのでそれを引き渡して使う
はよContextに対応してくれreact-server
対応はしてるんだよな https://github.com/facebook/react/blob/3dc41d8a2590768a6ac906cd1f4c11ca00417eee/packages/react-server/src/ReactFizzHooks.js#L259-L265
しかしreact-server-dom-webpackを見ると新しくなってないっぽくてだめ
v12.0.4-canary.0から使えるようになった Upgrade React alpha and experimental dependencies to latest (#31039) · vercel/next.js@5e185fc · GitHub
なってねー
ReactFizzはStreaming HTMLのことであって,React Server Componentsの実装であるReactFlightでは対応していない
Server Componentは(Contextを受けずに)自分が常にRootとして描画されることを考えないといけないから意図的に対応してないんじゃなかろうか?
RFC読んだほうがよさそう
404を返す方法がない(Streaming HTML)
getServerSidePropsが動作はするが,環境がmiddlewareと同じなのでresponseが{}になってて壊れており,{ notFound: true }を返すとUnhandled rejectionを投げた後何も返ってこなくなる
これはwebランタイム(いわゆる Edge Function)の結果
Refactor the middleware SSR loader by shuding · Pull Request #31508 · vercel/next.js · GitHubが入ったv12.0.5-canary.0以降ではAn error occurred while...といった感じの500エラーを返すようになった
いやresult == nullって404なんですよ
そもそもStreaming HTMLの設計上の問題という気もする
データ取得が完了する前にいろいろ生成して送ってしまっているわけで……
HTTPのセマンティクスに合っていない
それはそれとして明らかにページの主要なコンテンツに相当するデータが存在しない場合App Shellすら送るべきではないはずで,これは何とかしないといけないはず
HTTPErrorみたいなやつが最上位まで行ったらうまいことハンドルしてやるとかならうまくいきそう
何となくErrorをthrowしたら500は返せた
https://github.com/vercel/next.js/blob/d8028f553e6df7e159daa1f73ab1264214065bfb/packages/next/server/render.tsx#L1523 この辺で投げられてる
デバッガーアタッチしたけど変な挙動して何も見えない
ハンドルできてる場所はなさそう
next/headが動作しない(Streaming HTML)
Contextを利用しているがReact Server ComponentsのSSR時はClient Componentもサーバー上で実行されるので理論上は使えるように見える
HeadをClient Componentとしてラップして参照すればいい?と思うが,後述の理由でだめ
描画結果が遅延評価されているため,headを参照している場所でheadがまだ計算されていないという悲しみの理由により動いていない
現状<Head/>の中身を集めるオブジェクトをContextで取り回してrenderToStringしてからhead描画→body描画としているが,Streaming SSRだとこの前提が崩壊してしまうのでうまくいかないという感じ
正確に取り回すには最初の(Suspenseで囲まれていない部分の)出力を待ってから解析を進めればいいが,描画部分の設計を大きく書き直す必要がありそう(現状の実装だと今の描画パイプラインとバチバチに競合して地獄になる)
どの結果をheadの描画で使うべきみたいな戦略の話は↑のステータスコードと大体同じで,Suspenseで待たない部分がそのページで最も重要なデータであると考えればよさそう
Library Upgrade Guide: <head> (e.g. react-helmet) · Discussion #106 · reactwg/react-18 · GitHub
公式でも議論されてた
Suspenseを配置してストリーミングを行ってもブロックする(React Server Components)
サーバー側がちゃんとストリーミングをしているのにもかかわらず,クライアントがres.text()してしまってる
createFromFetchにフェイクのResponseを渡していたりしてなんか不穏な感じのコードである
Responseはstateとして管理されることが想定されているように見えるのになあ……
Client Componentでdefault export以外使えない
生成してるmanifestが雑すぎる(See: .next/server/middleware-flight-manifest.js)
from 2021-11