Why do I get ReferenceError: self is not Defined when I import the client library?
P粉214089349
P粉214089349 2023-10-21 12:53:53
0
1
745

I'm stuck while trying to create an xterm React component in Next.js because I can't get over an error message I've never received before.

I'm trying to import an npm client module called xterm, but if I add the import line, the application crashes.

import { Terminal } from 'xterm'

Error reading Server error... ReferenceError: self is not Defined Then display this code as Source

module.exports = require("xterm");

From some research I've done, this has to do with Webpack and it might be helpful if something like this is done:

output: {
  globalObject: 'this'
}

Do you know how to solve this problem?

P粉214089349
P粉214089349

reply all(1)
P粉958986070

This error occurs because the library requires Web API to work, and when Next.js prerenders the page on the server side.

In your case, xterm is trying to access a window object that does not exist on the server. The solution is to avoid loading xterm on the server and import it dynamically so that it is only loaded on the client.

In Next.js, there are multiple ways to achieve this.


#1 Use dynamic import() inside useEffect

Move import to the component's useEffect, then dynamically import the library and add logic there.

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

#2 Use next/dynamic with ssr: false

Create a component and add xterm logic to it.

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

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

export default TerminalComponent

Then dynamically import the component when used.

import dynamic from 'next/dynamic'

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

As an alternative, you can add logic directly when using next/dynamic to dynamically import the library to avoid generating extra files.

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
    }
)
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template