Chrome 105 では、Navigation API の NavigateEvent
に 2 つの新しいメソッドが導入されます(102 で導入)。これは、実務で問題となっているメソッドを改善するためのものです。intercept()
は、使用が困難であることが判明した transitionWhile()
に代わるもので、デベロッパーがナビゲーション後の状態を制御できるようにします。scroll()
メソッドは、URL で指定されたアンカーにスクロールします。restoreScroll()
はすべてのタイプのナビゲーションで機能しないため、scroll()
に置き換えられます。
この記事では、両方の方法の問題と、新しい方法でそれらの問題を解決する方法について説明します。
NavigateEvent.transitionWhile()
NavigateEvent.trasitionWhile()
メソッドは、Chrome 102 の Navigation API で導入され、シングルページ アプリのクライアントサイド遷移のナビゲーションをインターセプトします。最初の引数は、ブラウザとウェブ アプリケーションの他の部分に処理が完了したことを通知するプロミスです。
しかし、実際にはうまく機能しませんでした。次のような一般的なコーディング パターンについて考えてみましょう。
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 の仕様には、ウェブ デベロッパー向けの多くの情報が含まれています。