フロントエンド

Next.jsでアニメーションパッケージ(ScrollReveal)を使用する際の注意点

2022年11月6日

目次 [閉じる]

    はじめに

    Next.jsを使用しているプロジェクトにアニメーションを使用する機会があり、そこで、Next.jsの概念周りで理解力不足ではまった点があるので、記録として残しておきます。

    Next.js(ssgやssr)でアニメーションをする際の注意点

    自分がハマったのが、ScrollRevealというパッケージを使用して、スクロールすると対象の要素がふわっと浮き上がるアニメーションを実装しようとした時です。

    https://scrollrevealjs.org/

    以下コマンドで、パッケージをインストール
    yarn add scrollreveal
    yarn add @type/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を回避するということです。

    以下、修正後のコード

    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では、概念から理解しないとハマるところではハマるので難しいです。