このブログでは元々 ISR を使っていましたが、Notion の画像のリンク切れの問題を解消するために SSR に変更しました。しかし SSR はページの表示が遅いため、ページ遷移時に画面が固まったように見えるかもしれません。そこで今回は、ページ遷移時にローディングアニメーションを追加することでブログを見ている方に「画面遷移中です」ということを伝えられるようにします。
実装結果は以下です。
SSR に変更した経緯については、以下のページを見てください。
ローディングアニメーションを実装する
ローディングアニメーションの実装については、以下のページを参考にさせていただきました。
まずは components フォルダの直下に spinner フォルダを作成します。
spinner フォルダに Loader.tsx を作成し、以下のコードを追加します。
components/spinner/Loader.tsx
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { Spinner } from "./Spinner";
const Loader = () => {
const router = useRouter();
const [loading, setLoading] = useState(false);
useEffect(() => {
const handleStart = (url: string) =>
url !== router.asPath && setLoading(true);
const handleComplete = () => setLoading(false);
router.events.on("routeChangeStart", handleStart);
router.events.on("routeChangeComplete", handleComplete);
router.events.on("routeChangeError", handleComplete);
}, [router.events, router.asPath]);
return <>{loading && <Spinner />}</>;
};
export default Loader;
続いて、spinner フォルダに Spinner.tsx を作成し、以下のコードを追加します。
components/spinner/Spinner.tsx
import { FC } from "react";
export const Spinner: FC = () => {
return (
<>
<div className="loadingWrap">
<div className="loading" />
</div>
<style jsx>
{`
.loadingWrap {
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
left: 0;
z-index: 10;
}
.loading {
width: 5em;
height: 5em;
border-top: 1em solid rgba(255, 255, 255, 0.2);
border-right: 1em solid rgba(255, 255, 255, 0.2);
border-bottom: 1em solid rgba(255, 255, 255, 0.2);
border-left: 1em solid rgba(255, 255, 255, 1);
animation: loaderAnime 1s infinite linear;
border-radius: 50%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
z-index: 11;
}
@keyframes loaderAnime {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loadingNone {
animation: loadingAnime 1s forwards;
}
@keyframes loadingAnime {
0% {
opacity: 1;
}
99% {
opacity: 0;
}
100% {
opacity: 0;
display: none;
}
}
`}
</style>
</>
);
};
ちなみにローディングアニメーションの CSS については、以下のページを参考にさせていただきました。
最後に pages フォルダにある _app.tsx に以下を追加します。
pages/_app.tsx
import Loader from "../components/spinner/Loader"; //この行を追加
・
・
・
<GlobalStyle />
<Loader /> //この行を追加
<Component {...pageProps} />
これで実装が完了しました。
参考までに、このブログの今回の実装に関するコミットは以下です。
終わりに
今回は参考にさせていただいた記事のおかげで、簡単にローディングアニメーションを実装することができました。
現在は SSR を使っていますが、ISR + SWR 、もしくは 画像をキャッシュすることで、サイトを高速に表示しつつ画像のリンク切れ問題を解決することができそうなので、将来的にはチャレンジしたいと思っています。