窗口未定义 - Next.js 13 - 在服务器组件中使用客户端组件

3
Leaflet被导入到一个客户端组件的文件中,那么为什么服务器会运行它并抛出错误呢?
实际上,在重试后它确实可以工作,并最终成功渲染网站。
我尝试在useEffect内使用动态导入...但没有成功。

ReferenceError: window is not defined
    at eval (webpack-internal:///(sc_client)/./node_modules/leaflet/dist/leaflet-src.esm.js:305:17)
    at Object.(sc_client)/./node_modules/leaflet/dist/leaflet-src.esm.js (path/to/app.next/server/app/page.js:473:1)
    at __webpack_require__ (path/to/app.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///(sc_client)/./src/js/index.js:5:89)
    at Object.(sc_client)/./src/js/index.js (path/to/app.next/server/app/page.js:1845:1)
    at __webpack_require__ (path/to/app.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///(sc_client)/./src/components/Foo.jsx:9:70)
    at Object.(sc_client)/./src/components/Foo.jsx (path/to/app.next/server/app/page.js:1834:1)

# more logs ...

// app/page.js

import Foo from '@components/Foo';

export default function Base() {
  return (
    <main>
      <Foo />
    </main>
  );
}

// components/Foo.jsx

'use client';

import { useEffect } from 'react';
import { test } from '../js/index.js';

export default function Foo() {
  useEffect(() => {
    test();
  }, []);
  return <div>foo</div>;
}



// js/index.js

// Error thrown here cause calling window
import * as L from 'leaflet/dist/leaflet-src.esm.js';

const test = () => {
  console.log(L);
};

export { test };


1个回答

0
客户端组件中出现服务器错误的原因在 Next.js 存储库讨论中的 评论 中有很好的描述:

关于客户端指令存在一些混淆。它意味着这个组件在客户端上运行。我看到了很多材料说只有。而客户端组件就像我们之前编写的组件一样。为了从服务器发送完整的 HTML 框架,客户端组件也在服务器上运行!

当您尝试动态导入时,是否指定了 ssr: false 选项?以下是 Next.js 文档的 无 SSR 章节的摘录:

要在客户端动态加载组件,可以使用 ssr 选项禁用服务器渲染。如果外部依赖项或组件依赖于浏览器 API(如 window),则此选项非常有用。

import dynamic from 'next/dynamic';
 
const DynamicHeader = dynamic(() => import('../components/header'), {
  ssr: false,
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接