はじめに
Next.jsを使用しているプロジェクトにアニメーションを使用する機会があり、そこで、Next.jsの概念周りで理解力不足ではまった点があるので、記録として残しておきます。
Next.js(ssgやssr)でアニメーションをする際の注意点
自分がハマったのが、ScrollRevealというパッケージを使用して、スクロールすると対象の要素がふわっと浮き上がるアニメーションを実装しようとした時です。
https://scrollrevealjs.org/
//jacascript インストール
npm i (yarn add) scrollreveal
//typescriptインストール
npm i (yarn add) @types/scrollreveal
まず、すのReactでのコードを見ていきます。
import { useRef, useEffect } from "react";
import { NextPage } from "next";
// ビルド時にimportしている
import scrollReveal from "scrollreveal";
type Props = {
move: string;
delay: number
className?: string
}
const ScrollReveal: NextPage<Props> = ({
children,
move,
delay,
className
}) => {
const sectionRef = useRef<HTMLDivElement>(null);
useEffect(() => {
async function animate() {
if (sectionRef.current) {
//ここに注目
scrollReveal().reveal(sectionRef.current, {
delay: delay,
opacity: 0,
origin: move,
distance: "20px",
viewFactor: 0.2
})
}
}
animate()
}, [sectionRef])
return <div className={`${className}`} ref={sectionRef}>{children}</div>
};
export default ScrollReveal;
このように、記述できます。
しかし、Next.jsでSSG(静的サイトジェネレーション)、SSR(サーバーサイトジェネレーション)を用いた開発を行う際、yurn build もしくは npm run buildする際に document is not defined というエラーが出てきます。
エラーの原因
ScrollRevealパッケージをimportする際、パソコンの情報(windowの横、縦幅など)が必要なんですが、ビルド時には、それらの情報は存在しないのでエラーが出ます。
解決策
ビルド時にScrollRevealをimportせずに、ユーザーがパソコンでサイトを開いたタイミングでScrollRevealをimportする。
具体的な解決策
まず、Next.jsには Dynamic import というパッケージのimport方法があるのでこの技術を使用してエラー回避します。
Dynamic Import
これは、動的にパッケージをimportする技術です。(動的というとわかりにくいので、ユーザーがサイトを開いたタイミングというふうに認識しています。間違ってたらごめんなさい。。。)
つまり、ビルド時、サーバーサイドではScrollRevealパッケージをimportせずに、ユーザーがサイトを訪れたタイミングで初めてimportし、document is not definedを回避するということです。
Next.jsでのコード
import { useRef, useEffect } from "react";
import { NextPage } from "next";
//importしていない
type Props = {
move: string;
delay: number
className?: string
}
const ScrollReveal: NextPage<Props> = ({
children,
move,
delay,
className
}) => {
const sectionRef = useRef<HTMLDivElement>(null);
useEffect(() => {
async function animate() {
if (sectionRef.current) {
//Dynamic import
const sr = (await import("scrollreveal")).default
sr().reveal(sectionRef.current, {
delay: delay,
opacity: 0,
origin: move,
distance: "20px",
viewFactor: 0.2
})
}
}
animate()
}, [sectionRef])
return <div className={`${className}`} ref={sectionRef}>{children}</div>;
};
export default ScrollReveal;
このように記述を変更すれば、エラー回避できます!!
まとめ
Next.jsでは、概念から理解しないとハマるところではハマるので難しいです。