Chrome 105 では、Navigation API の NavigateEvent
に 2 つの新しいメソッドが導入されます(102 で導入)。これは、実務で問題となっているメソッドを改善するためのものです。transitionWhile()
は使用が困難であることが判明したため、デベロッパーがナビゲーション後の状態を制御できる intercept()
に置き換えられました。restoreScroll()
はすべてのタイプのナビゲーションで機能しないため、URL で指定されたアンカーにスクロールする scroll()
メソッドに置き換えられます。
この記事では、両方の方法の問題と、新しい方法でそれらの問題を解決する方法について説明します。
NavigateEvent.transitionWhile()
Chrome 102 の Navigation API で導入された NavigateEvent.trasitionWhile()
メソッドは、シングルページ アプリのクライアントサイドでの遷移でナビゲーションをインターセプトします。最初の引数は、ブラウザとウェブ アプリケーションの他の部分に処理が完了したことを通知するプロミスです。
これは実際にはうまく機能しませんでした。次の一般的なコーディング パターンについて考えてみましょう。
event.transitionWhile((async () => {
doSyncStuff();
await doAsyncStuff();
})());
これは機能的には以下のコードと同等です。これにより、デベロッパーがナビゲーションをインターセプトする意図があることを API が認識する前に、ナビゲーションの一部が実行されます。
doSyncStuff();
event.transitionWhile((async () => {
await doAsyncStuff();
})());
これがアプリにおかしくなる可能性がある一例として、スクロール復元ロジックがあります。この場合、DOM 変更前ではなく後、スクロール位置がキャプチャされます。
変更内容
transitionWhile()
を置き換えるために、現在の仕様では NavigateEvent.intercept()
が導入されています。新しいメソッドは、transitionWhile()
でサポートされている focusReset
プロパティと scrollRestoration
プロパティに加えて、ハンドラを受け取ります。新しいハンドラは、ナビゲーション コミット後に常に実行され、スクロール位置などの情報がキャプチャされるため、transitionWhile()
の問題を回避できます。
transitionWhile()
メソッドは引き続き使用できますが、非推奨であり、Chrome 108 で削除される予定です。
intercept() を使用する
NavigateEvent.intercept()
には、transitionWhile()
と同じ制限があります。つまり、すべてのナビゲーション イベントで呼び出すことはできません。クロスオリジン ナビゲーションをインターセプトすることはできません。また、ドキュメント間の移動もインターセプトできません。これにより、"SecurityError"
型の DOMException
がスローされます。
intercept()
を使用するには、呼び出すときにカスタム ハンドラを渡すだけです。
navigation.addEventListener("navigate", event => {
event.intercept({
async handler() {
doSyncStuff();
await doAsyncStuff();
}
});
});
NavigateEvent.scroll()
ページの上部からアンカーへの移動(/a
から /a#id
への移動)などのナビゲーションは、シングルページ アプリでもブラウザによって完全に処理されます。ただし、別の「ページ」のアンカーへの移動(/a
から /b#id
への移動)は、マルチページ アプリでは簡単ですが、シングルページ アプリでは複雑になります。アプリは、NavigateEvent.transitionWhile()
を使用して /b#id
へのナビゲーションをインターセプトしてから、NavigateEvent.restoreScroll()
を呼び出してアンカーを表示する必要があります。前述のとおり、現時点では難しい作業です。
変更内容
シングルページ アプリで、アンカーへのスクロールをブラウザが処理するか、コードが処理するかを制御できるようになりました。
scroll() の使用
デフォルトでは、インターセプト ハンダーが満たされると、ブラウザはスクロールを自動的に処理しようとします。スクロールを自分で処理する場合は、scroll
を "manual"
に設定し、ブラウザがスクロール位置の設定を試みるときに NavigateEvent.scroll()
を呼び出します。
navigation.addEventListener("manual", event => {
scroll: "manual",
event.intercept({
async handler() {
doSyncStuff();
// Handle scrolling earlier than by default:
event.scroll();
await doAsyncStuff();
}
});
});
restoreScroll()
メソッドは引き続き使用できますが、非推奨であり、Chrome 108 で削除される予定です。
まとめ
Navigation API に関する記事は近日中に更新される予定です。一方、この API の仕様には、ウェブ デベロッパー向けの多くの情報が含まれています。