heavy SSR makes TTFB longer
In NextJS, the heavy getServerSideProps
method freeze user transition. For example, If sleep 5sec in getServerSideProps
, the user need wait 5 sec after clicking a link.
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 is bad UX demo. You should wait 5 sec after clicking a link. This will be bad experience for user.
solution: use router.change
NextJS has a Router.event('eventName', ()=>{})
method. This method can handle events of routing change. Especially "routeChangeStart"
can handle the start point of change routing. Then if you toggle state which manages to show loading or not, you can show loader.
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>
);
};
here is demo.
Top comments (2)
I just pulled in react-topbar-progress-indicator from NPM and connected it to the same routing events, works equally well and the user is not left waiting with nothing happening
Thank for it. useRoutes().events Doesn't work for me.