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

Posted

技术标签:

【中文标题】为啥我在导入客户端库时收到 ReferenceError: self is not defined?【英文标题】:Why am I getting ReferenceError: self is not defined when I import a client-side library?为什么我在导入客户端库时收到 ReferenceError: self is not defined? 【发布时间】:2021-05-11 17:48:54 【问题描述】:

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

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

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 pre-renders the page 时这些 API 不可用。

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

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


#1 使用动态import()

import 移动到组件的useEffect,然后动态导入库并在其中添加逻辑。

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

#2 使用next/dynamics-s-r: 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'), 
    s-s-r: 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 <></>
        
    ,
    
        s-s-r: false
    
)

【讨论】:

感谢您的回复!我已经尝试过了,但它似乎没有导入 Terminal 构造函数。相反,我得到的是带有 $$typeof:render: 属性的 someobject = 。你知道为什么会这样吗? 我已经通过在我的组件中执行import Terminal from 'xterm' 然后在父页面中使用dynamic() 函数导入该&lt;Component /&gt; 来解决它。如果您提及此细节,我可以将您的答案标记为正确。 对了,我假设Terminal 是一个组件——Next.js dynamic 必须返回一个组件。我会更新我的答案。

以上是关于为啥我在导入客户端库时收到 ReferenceError: self is not defined?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 sagemaker 笔记本中导入 SparkContext 库时出现错误?

我在导入 PyDictionary 库时遇到问题

为啥我在 facenet 中收到此错误?

为啥我在 discord.js 中收到客户端错误

使用 python setuptools 库时的导入问题

为啥我在 Nodejs 中收到“无法在将标头发送到客户端后设置标头”错误?