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粉9589860702023-10-22 10:48:55
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.
import()
inside
useEffectMove 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() }, [])
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 } )