Next.js における View Transition API

#雑記


iOS や macOS のプレビュー版 Safari で View Transition API が使えるようになった。

https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API#browser_compatibility


Next.js で異なる document を跨ぐ View Transition API を実現するためのディスカッションが行われている


Next.js App Router で検証された実装例がいくつか上がっている。


View Transition API を Next.js の世界に持ってくるためのボトルネックは、Next.js のレンダリング (DOM 更新) とネットワークリクエスト処理の混在が原因であるという指摘がある

Basically the thing to understand is that Next.js's approach to network requests is very 'messy' (messy in terms of being initiated from the same code which updates the DOM), thus integrating it with the view transition API in a way that works for slow network speeds is hard. In contrast, for many other frameworks each route has a clear 'retrieve data' step, which makes it trivial to integrate with the view transition API. The crucial thing for the View Transition API is that network requests and DOM updates need to be separated, something that will - I believe - require major changes in how to think about a Next.js app and a new approach to marking data to be loaded before a route is rendered. Hopefully people smarter than me can figure out how to make this work within the mental model of Next.js... but 🤷[1] . Anyway, my point is, there is good reason for Next.js to not have this, whilst some frameworks could implement this in mere hours.

基本的に理解すべきことは、ネットワークリクエストに対するNext.jsのアプローチは非常に「雑」(DOMを更新するのと同じコードから開始されるという意味で雑)なので、低速なネットワーク速度に対応する方法でビュー遷移APIと統合するのは難しいということです。対照的に、他の多くのフレームワークでは、各ルートには明確な「データを取得する」ステップがあり、ビュー遷移APIと統合するのは簡単です。ビュー遷移APIにとって重要なのは、ネットワークリクエストとDOMの更新を分離する必要があるということです。このためには、Next.jsアプリの考え方を大きく変え、ルートがレンダリングされる前に読み込むデータをマークする新しいアプローチが必要になると思います。私よりも賢い人たちが、Next.jsのメンタルモデルの中でこれをうまく機能させる方法を見つけ出してくれるといいのですが......🤷[1] 。いずれにせよ、私が言いたいのは、Next.jsがこれを備えていないのには十分な理由があるということです。

https://github.com/vercel/next.js/discussions/46300#discussioncomment-9081595


一方、React における MPA の View Transition API のボトルネックは、React の Suspense にあるという指摘がある。

IMO the behavior of "View Transition" is not well-defined in the context of Suspense and data fetching. The actual model is not just this:

Route A -> Click Link -> Fetch Data -> Render Route B
                                                               ^(transition)

But sometimes like this (parallelized data fetching and rendering):

Route A -> Click Link -> Fetch Data (Streaming)
                                             -> Route Navigation Fully Finished
                                                     -> Render Component A (inside <Suspense>)
                                                              -> Render Component B (inside <Suspense>)
                                                                       -> ...

And there is no clear moment that the route navigation is done. Personally, I'm not sure what will be the correct way to model this so, I'd wait for the React team to come up with a new primitive of transition animations first. Don't think it's specifically a Next.js issue.

IMOは、「View Transition 」の動作は、サスペンデッドとデータフェッチの文脈ではよく定義されていません。実際のモデルはこうではない:

ルートA -> リンクをクリック -> データをフェッチ -> ルートBをレンダリング
(遷移)
並列化されたデータ・フェッチとレンダリング):

ルートA -> リンクをクリック -> データをフェッチ(ストリーミング) -> ルート・ナビゲーションが完全に終了 -> コンポーネントAをレンダリング(内部)。
-> コンポーネントAをレンダリング(<サスペンス>内)
-> コンポーネントBのレンダリング(<Suspense>内)
-> ...
と、ルートナビゲーションが終わったという明確な瞬間がない。個人的には、これをモデル化する正しい方法が何なのかわからないので、まずはReactチームがトランジション・アニメーションの新しいプリミティブを考え出すのを待ちたいと思います。特にNext.jsの問題だとは思いません。

これは Next.js だけでなく React Suspense を実装する際は HTTP レスポンスが Streaming になるため、レスポンスの途中にあるはずの Suspense を埋め込んだ document の受信を完了したことが document.startViewTransition 呼び出し側で判断できないため、と理解した。この判断ができなければ、確かに遷移前の画面から document.startViewTransition を呼び出すタイミングは図れないし、これは Next.js だけでなく React 側の都合であるとも考える事もできそうだ。


Next.js のメンテナ (Vercel 所属) の方が提供されているライブラリがある。まあこれも「ハックである」と上記コメントの方が指摘しているが。


popstate イベントなどを見て startViewTransition を実行する感じに見えるが、前後で細かい制御を入れているようだ。後ほど細かく見ていきたい


この記事が気に入ったらサポートをしてみませんか?