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

Uppy在Next.js中报"document is not defined"错误的解决办法

在Next.js中集成Uppy的解决方案

Next.js的服务端渲染环境没有document、window这类浏览器API,而Uppy依赖这些API运行,下面是几种可行的解决办法:

方法1:动态导入并禁用SSR(推荐)

用Next.js自带的next/dynamic工具,将Uppy相关组件设置为仅客户端加载,避免服务端渲染时触发API缺失错误。

步骤:

  1. 创建单独的Uppy组件文件(比如UppyUploader.tsx),在里面正常初始化Uppy:
import Uppy from '@uppy/core';
import DragDrop from '@uppy/drag-drop';
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';
import { useEffect, useRef } from 'react';

export default function UppyUploader() {
  const uppyRef = useRef<Uppy | null>(null);

  useEffect(() => {
    // 初始化Uppy实例
    if (!uppyRef.current) {
      const uppy = new Uppy()
        .use(DragDrop, { target: '#drag-drop-area' });

      uppy.on('complete', (result) => {
        console.log('上传完成:', result.successful);
      });

      uppyRef.current = uppy;
    }

    // 组件卸载时清理实例,避免内存泄漏
    return () => {
      uppyRef.current?.close();
    };
  }, []);

  return (
    <div id="drag-drop-area">
      <p>拖放文件到这里,或点击选择文件</p>
    </div>
  );
}
  1. 在页面文件(比如page.tsx)中动态导入该组件,设置ssr: false:
import dynamic from 'next/dynamic';

const UppyComponent = dynamic(() => import('./UppyUploader'), {
  ssr: false,
  loading: () => <p>加载上传组件中...</p>
});

export default function Home() {
  return (
    <div>
      <h1>文件上传</h1>
      <UppyComponent />
    </div>
  );
}

方法2:通过环境判断仅在客户端初始化

如果不想拆分组件,可以在页面代码中通过typeof window !== 'undefined'判断当前环境,只在客户端执行Uppy的初始化逻辑:

import Uppy from '@uppy/core';
import DragDrop from '@uppy/drag-drop';
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';
import { useEffect, useRef } from 'react';

export default function Home() {
  const uppyRef = useRef<Uppy | null>(null);

  useEffect(() => {
    // 仅在浏览器环境中初始化Uppy
    if (typeof window !== 'undefined' && !uppyRef.current) {
      const uppy = new Uppy()
        .use(DragDrop, { target: '#drag-drop-area' });

      uppy.on('complete', (result) => {
        console.log('上传结果:', result);
      });

      uppyRef.current = uppy;
    }

    return () => {
      uppyRef.current?.close();
    };
  }, []);

  return (
    <div>
      <h1>文件上传</h1>
      <div id="drag-drop-area">拖放文件到这里上传</div>
    </div>
  );
}

方法3:Next.js 13+ App Router 用"use client"指令

如果你用的是Next.js 13及以上的App Router,直接在Uppy组件顶部加上'use client'标记,该组件就会被视为纯客户端组件,不会在服务端渲染:

UppyUploader.tsx:

'use client';

import Uppy from '@uppy/core';
import DragDrop from '@uppy/drag-drop';
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';
import { useEffect, useRef } from 'react';

export default function UppyUploader() {
  const uppyRef = useRef<Uppy | null>(null);

  useEffect(() => {
    if (!uppyRef.current) {
      const uppy = new Uppy()
        .use(DragDrop, { target: '#drag-drop-area' });

      uppyRef.current = uppy;
    }

    return () => {
      uppyRef.current?.close();
    };
  }, []);

  return <div id="drag-drop-area">拖放文件到这里</div>;
}

page.tsx:

import UppyUploader from './UppyUploader';

export default function Home() {
  return (
    <main>
      <h1>文件上传页面</h1>
      <UppyUploader />
    </main>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:01:12