diff --git a/app/routes/posts/soft-hard-navigation-and-bfcache.mdx b/app/routes/posts/soft-hard-navigation-and-bfcache.mdx new file mode 100644 index 0000000..04dd541 --- /dev/null +++ b/app/routes/posts/soft-hard-navigation-and-bfcache.mdx @@ -0,0 +1,140 @@ +--- +title: "ソフトナビゲーションの仕組みと使い方" +description: "BFCacheの挙動について調べている際、ソフトナビゲーションとハードナビゲーションというワードを知ったので、メモがてらブログにまとめます" +date: "2024/12/11" +updatedAt: "2024/12/11" +path: "soft-hard-navigation-and-bfcache" +published: true +--- + +[2024年 ユウトの一人アドベントカレンダー](https://adventar.org/calendars/9980)の11日目の記事です。 + +## Intro + +BFCacheの挙動について調べている際、ソフトナビゲーションとハードナビゲーションというワードを知った(正確には教えてもらった)ので、メモがてらブログにまとめます。 + +## ソフトナビゲーションとは + +仕様書には以下のように記載があります。 + +> “Soft navigations” are JS-driven same-document navigations that are using the history API or the new Navigation API, triggered by a user gesture and modifies the DOM, modifying the previous content, as well as the URL displayed to the user. +> ref: https://github.com/WICG/soft-navigations/blob/main/README.md#overview + +HistoryやNavigation、history.pushStateやnavigation.navigateなどのJavaScript APIを使ってDOM, URLを変更することをソフトナビゲーションと呼ぶそうです。 + +## ハードナビゲーションとは + +先ほどの「ソフト」という言葉と違い、こちらは「ハード」となっています。 + +その名前の通り、ハードナビゲーションは、ページ全体をロードするナビゲーションのことを指します。なのでaタグや、`window.location.reload`などがこちらに該当します。 + +どちらかといえばこちらが従来の画面遷移で、いわゆるMPAで使用されていた画面遷移方法になります。 + +## ソフトナビゲーションはなぜ生まれたのか + +こちらも仕様書から抜粋。 + +> - Developers would like to attribute various performance entries to specific “soft navigation” URLs. For example, layout shifts caused in one URL can currently be attributed to the corresponding landing page, resulting in mis-attribution and trouble finding the real cause and fixing it. +> - Developers would like to receive various “load” performance entries for soft navigations. Specifically, paint timing entries seem desired for such navigations. + +> From a user's perspective, while they don't necessarily care about the architecture of the site they're visiting, they likely care about it being fast. This specification would enable alignment of the measurements with the user experience, improving the chances of SPA sites being perceived as fast by their users. + +> ref: [https://github.com/WICG/soft-navigations/blob/main/README.md#motivation](https://github.com/WICG/soft-navigations/blob/main/README.md#motivation) + +メインはパフォーマンスの正確な測定ということがあります。 +そしてこれに対してさらにポイントは二つあり、それが開発者視点とアプリを使用するユーザー視点です。 + +それぞれ少しみていきましょう。 + +### 開発者視点 + +ソフトナビゲーションが生まれる前の課題として、**測定したいページと、実際に測定されたページが異なる**という問題が発生していました。 + +つまりどういうことか、これは[Fire Paint Timing events for soft navigations](https://github.com/w3c/performance-timeline/issues/168)というissueのコメントに、以下のように記載があります。 + +> This is especially noticeable on something like CLS: +User lands on example.com/foo +The observers are initialised and data collected +User clicks to example.com/foo/bar +The observers are still running from example.com/foo, and also the new 'page' example.com/foo/bar +> +> ref: [https://github.com/w3c/performance-timeline/issues/168#issue-640604757](https://github.com/w3c/performance-timeline/issues/168#issue-64060475) + +fooというパスから、foo/barに読み込みが終わる前に遷移すると、CLSの結果がfoo + foo/barの結果になってしまう。というバグですね。 + +Core Web Vitalsを元にしたWebのパフォーマンス改善をしたことがある方であれば、共感できる内容ではないでしょうか。 +筆者も確かに同じような経験をしたことがあった気がしたのですが、その環境を用意しようとしましたところなかなかうまくできなかったのでそちらは断念しました。 + +### ユーザー視点 + +これは開発者がCore Web Vitalsなどの指標をあげやすくなることでデバッグしやすくなり、そうなるとアプリのパフォーマンスが良くなる。 + +そしてアプリを使用するユーザーは高速であって欲しいはずだから、UXも良くなっているはず。という意見かと思っています。 + +## ソフトナビゲーションを使ってみる + +なんとなくソフトナビゲーションについて理解できたところで、実際に触ってみましょう。 + +まず、この機能はデフォルトで有効になっていないので、有効化する必要があります。 + +ブラウザで、[chrome://flags/#enable-experimental-web-platform-features](chrome://flags/#enable-experimental-web-platform-features)にアクセスして、disbaleからenableに変更しましょう。 +あとこれはChromiumでしかまだ試せません。 + +有効にできたら実際にAPIレベルで触ってみます。 + +以下のようなコードを実行してみます。筆者はReactで試しているので、このコードをそのままuseEffect内で実行します。 + +```js +new PerformanceObserver((entryList) => { + for (const entry of entryList.getEntries()) { + const softNavEntry = + performance.getEntriesByType('soft-navigation').filter( + (navEntry) => navEntry.navigationId === entry.navigationId + )[0]; + console.log("softNavEntry", softNavEntry); + + const hardNavEntry = performance.getEntriesByType('navigation')[0]; + const navEntry = softNavEntry || hardNavEntry; + const startTime = navEntry?.startTime; + console.log('LCP time:', entry.startTime - startTime); + } +}).observe({ type: 'largest-contentful-paint', buffered: true, includeSoftNavigationObservations: true }); +``` +ポイントは`includeSoftNavigationObservations: true`で、このオプションをつけることで、ソフトナビゲーションでパフォーマンスの監視を行ってくれるようになります。 + +そしてフラグの有効化と、先ほどのコードを実行すると、以下のような結果になるかと思います + +
Flag OFF | +Flag ON | +
---|---|
+ + | ++ + | +