为什么我在导入客户端库时收到 ReferenceError: self is not defined?

IT技术 reactjs webpack next.js xtermjs
2021-04-08 00:12:39

尝试Next.js 中创建一个xterm react 组件时我被卡住了,因为我无法克服以前从未收到过的错误消息。

我正在尝试导入一个名为 的 npm 客户端modulexterm,但是如果我添加导入行,应用程序就会崩溃。

import { Terminal } from 'xterm'

错误读取Server Error... ReferenceError: self is not defined 然后将此代码块显示为Source

module.exports = require("xterm");

根据我所做的一些研究,这与 Webpack 有关,如果这样做会有所帮助:

output: {
  globalObject: 'this'
}

你知道如何解决这个问题吗?

1个回答

发生该错误是因为该库需要 Web API 才能工作,当Next.js在服务器端预渲染页面时,这些 API 不可用

在您的情况下,xterm尝试访问window服务器上不存在对象。要修复它,您必须动态导入,xterm以便它仅在客户端加载。

在 Next.js 中有几种方法可以实现这一点。


使用动态 import()

将 移动import到您的组件的useEffect,然后动态导入库并在那里添加您的逻辑。

useEffect(() => {
    const initTerminal = async () => {
        const { Terminal } = await import('xterm')
        const term = new Terminal()
        // Add logic with `term`
    }
    initTerminal()
}, [])

使用next/dynamicssr: false

创建一个组件,您可以在其中添加xterm逻辑。

// components/terminal-component
import { Terminal } from 'xterm'

function TerminalComponent() {
    const term = new Terminal()
    // Add logic around `term`
    return <></>
}

export default TerminalComponent

然后在使用时动态导入该组件。

import dynamic from 'next/dynamic'

const TerminalComponent = dynamic(() => import('<path-to>/components/terminal-component'), {
    ssr: false
})

作为替代方案,您可以在动态导入库时直接添加逻辑,next/dynamic以避免为它添加额外的文件。

import dynamic from 'next/dynamic'

const Terminal = dynamic(
    {
        loader: () => import('xterm').then((mod) => mod.Terminal),
        render: (props, Terminal) => {
            const term = new Terminal()
            // Add logic with `term`
            return <></>
        }
    },
    {
        ssr: false
    }
)
感谢您的答复!我试过这个,但它似乎没有导入{ Terminal }构造函数。我得到的是someobject = {}带有 a$$typeof:render:属性的。你知道为什么会这样吗?
2021-05-23 00:12:39
我已经通过import { Terminal } from 'xterm'在我的组件中执行一个然后在父页面<Component />使用dynamic()函数导入它来解决它如果您提到这个细节,我可以将您的答案标记为正确。
2021-05-28 00:12:39
啊对了,我假设Terminal是一个组件 - Next.jsdynamic必须返回一个组件。我会更新我的答案。
2021-06-01 00:12:39