[ NextJS ] SSRのスムーズルーティング


重いSSRはTTFBを長くする


NextJSでは、重いgetServerSidePropsメソッド凍結ユーザー移行.例えば、getServerSidePropsの睡眠5秒なら、ユーザはリンクをクリックした後5秒待つ必要がある.
import Link from "next/link";

export default () => {
  return <Link href="about">heavy about</Link>;
};
export default (props) => {
  return <div>this is about page: {props.id}</div>;
};

export async function getServerSideProps(context) {
  await sleepByPromise(5);
  return {
    props: { id: 1 }, // will be passed to the page component as props
  };
}

function sleepByPromise(sec) {
  return new Promise((resolve) => setTimeout(resolve, sec * 1000));
}
Hereは、悪いUXデモです.リンクをクリックした後、5秒待ってください.これはユーザーの悪い経験になります.

ソリューション:使用ルータ。チェンジ


NextjsはRouter.event('eventName', ()=>{})の方法を持っています.このメソッドはルーティング変更のイベントを処理できます.特に"routeChangeStart"は変更ルーティングの出発点を扱うことができます.次にローディングを表示する状態を切り替える場合は、ローダを表示できます.
import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

export default () => {
  const [isLoading, setLoadingState] = useState(false);
  const router = useRouter();
  useEffect(() => {
    router.events.on("routeChangeStart", (url) => {
      setLoadingState(true);
    });
  }, []);
  return isLoading ? (
    <div
      style={{
        background: "rgba(0,0,0,0.8)",
        color: "white",
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        fontSize: 32,
        position: "fixed",
        top: 0,
        left: 0,
        width: "100vw",
        height: "100vh",
      }}
    >
      <marquee>loading</marquee>
    </div>
  ) : (
    <Link href="about">heavy about</Link>
  );
};

こちらはdemoです.

ソースコード


https://github.com/ojisan-toybox/next-js-routing-inidicator