You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13集成lottie-react出现ReferenceError:SSR兼容性问题?

问题描述

在Next.js 13项目中安装lottie-react后,项目编译成功,但运行时抛出ReferenceError,提示document is not defined,错误日志如下:

✓ Compiled in 104ms (1559 modules)
⨯ ReferenceError: document is not defined
    at createTag (/Users/thomas/starknetid/app.starknet.id/node_modules/lottie-web/build/player/lottie.js:30:5)
    at /Users/thomas/starknetid/app.starknet.id/node_modules/lottie-web/build/player/lottie.js:1316:20
    at /Users/thomas/starknetid/app.starknet.id/node_modules/lottie-web/build/player/lottie.js:1323:6
    at /Users/thomas/starknetid/app.starknet.id/node_modules/lottie-web/build/player/lottie.js:1540:4
    at /Users/thomas/starknetid/app.starknet.id/node_modules/lottie-web/build/player/lottie.js:2:83
    at Object.<anonymous> (/Users/thomas/starknetid/app.starknet.id/node_modules/lottie-web/build/player/lottie.js:5:3)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Module._load (node:internal/modules/cjs/loader:1023:12)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at mod.require (/Users/thomas/starknetid/app.starknet.id/node_modules/next/dist/server/require-hook.js:64:28)
    at require (node:internal/modules/helpers:176:18)
    at Object.<anonymous> (/Users/thomas/starknetid/app.starknet.id/node_modules/lottie-react/build/index.js:5:14)
    at Module._compile (node:internal/modules/cjs/loader:1376:14) {
  page: '/register/testingdomain.stark'
}

推测问题源于lottie-react的SSR兼容性——客户端环境中document已定义,但SSR环境无法访问该对象。现需了解:在SSR场景下,lottie-react与Next.js集成的解决方案或最佳实践;是否需要在每个使用lottie的组件中判断SSR状态?

解决方案与最佳实践

1. 动态导入并禁用SSR(推荐)

利用Next.js的动态导入功能,将lottie-react组件标记为仅在客户端渲染,无需手动判断SSR状态。示例代码:

import dynamic from 'next/dynamic';

const Lottie = dynamic(() => import('lottie-react'), {
  ssr: false,
  loading: () => <div>加载中...</div> // 可选:添加加载占位符
});

// 使用组件
export default function MyLottieComponent() {
  return <Lottie animationData={yourAnimationData} />;
}

这种方式会自动跳过SSR阶段,仅在客户端加载组件,从根源避免document未定义的问题。

2. 组件内判断客户端环境

如果需要更细粒度的控制,可以在组件内部通过typeof window !== 'undefined'判断是否处于客户端环境,再渲染lottie内容:

import Lottie from 'lottie-react';

export default function MyLottieComponent() {
  if (typeof window === 'undefined') {
    return <div>占位内容</div>; // SSR阶段返回占位符
  }
  
  return <Lottie animationData={yourAnimationData} />;
}

这种方法适合需要在SSR阶段展示自定义占位内容的场景,但需要在每个使用lottie的组件中重复判断逻辑。

3. 封装通用Lottie组件

为了避免重复编写判断逻辑,可以封装一个通用的客户端Lottie组件,在项目中统一使用:

// components/ClientLottie.js
import dynamic from 'next/dynamic';

const Lottie = dynamic(() => import('lottie-react'), {
  ssr: false,
  loading: () => <div>加载中...</div>
});

export default Lottie;

之后在项目中直接导入这个封装好的组件即可,无需每次处理SSR逻辑。

4. 使用lottie-web的纯客户端初始化

如果不想用lottie-react封装,也可以直接使用lottie-web,并在useEffect中初始化(仅在客户端执行):

import { useEffect, useRef } from 'react';
import lottie from 'lottie-web';

export default function MyLottieComponent() {
  const containerRef = useRef(null);

  useEffect(() => {
    if (containerRef.current) {
      lottie.loadAnimation({
        container: containerRef.current,
        animationData: yourAnimationData,
        loop: true
      });
    }
  }, []);

  return <div ref={containerRef} />;
}

useEffect的回调函数仅在客户端渲染完成后执行,自然避开SSR环境。

总结
  • 优先使用动态导入禁用SSR的方案,简洁高效,无需重复逻辑;
  • 若需自定义SSR占位内容,可在组件内判断客户端环境;
  • 封装通用组件能进一步简化项目中的使用流程;
  • 直接使用lottie-web结合useEffect也是可靠的替代方案。

内容的提问来源于stack exchange,提问作者Th0rgal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:47:22