75

Why node.js does not recognize document.GetElementById? It says 'ReferenceError: document is not defined'. What can I do?

ReferenceError: document is not defined
at Object.<anonymous> (C:\Users\Desktop\main.js:9:18)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
Alireza
  • 100,211
  • 27
  • 269
  • 172
Ela
  • 859
  • 1
  • 6
  • 11
  • 9
    because... node.js doesn't have DOM like the browser does built-in. – Kevin B Aug 20 '15 at 18:53
  • 3
    @KevinB: can you post that answer so it can be accepted, please? Thanks. – Felix Aug 20 '15 at 19:02
  • 1
    @Felix Remus already has. – Kevin B Aug 20 '15 at 19:03
  • 1
    Considering the fact you are trying to get a value based on ID and I'm just trying to do the same, this answer might be of much greater use to you http://stackoverflow.com/questions/7977945/html-parser-on-node-js – iBobb Dec 23 '16 at 15:59
  • 2
    try `window.document.getElementById` instead – Jacksonkr Jul 27 '20 at 16:59
  • @Jacksonkr Node also doesn’t have a `window`. Why should one “try” that? – Sebastian Simon Jun 12 '21 at 14:30
  • @SebastianSimon Please excuse me, ReactJS was on the brain. You are absolutely correct: out of the box `node` has no idea what `document` nor `window` are. If you are using node with `commonJS` or some sort of browser-friendly environment you may need to listen for some sort of dom-loaded event before accessing global browser objects. Depending on your situation a cheap trick may be to add a `try catch` – Jacksonkr Jun 13 '21 at 04:09

7 Answers7

69

document relates to the DOM (Document Object Model) in a web browser.

Node.js, however, is not a browser environment. It is a server environment, much like PHP or Perl, and as such, you can’t access the browser’s DOM or do anything specific to browser-hosted JavaScript.

The closest you could get is using something like to include Node.js modules in your client-side code.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
brandonscript
  • 68,675
  • 32
  • 163
  • 220
  • Can you point me to some code that uses `browserify` that does exactly this? – lifebalance May 30 '16 at 18:31
  • 1
    Nope, but they've got [docs](https://github.com/substack/node-browserify#usage). Keep in mind, the behaviour of a client app (DOM-accessible) is massively different from a server app. You won't be able to start up a server or do any server-related activities in the browser with browserify; it's mostly for taking cleanly-packaged NPM modules (e.g. Moment.js or Lodash) and making them available. – brandonscript May 30 '16 at 18:32
  • 1
    I find this answer could be of much more use if you were to provide cases where we NEED to emulate the browser dom server side for certain libraries such as pdf.js. – vasilevich Nov 23 '16 at 14:55
  • 2
    Sure, but that wasn't what the question was about. Ask a new one if you need to. – brandonscript Nov 23 '16 at 15:19
  • And webpack. And esbuild. And parcel. And rollup. – code Mar 19 '22 at 19:43
  • https://browserify.org/ – sanjeev Jun 26 '22 at 17:45
56

You could use JSDom to add Dom support to Node. To make a variable global you can use either

GLOBAL.document = new JSDOM(html).window.document;

or

global.document = new JSDOM(html).window.document;

where html is your website as a string.

To use JSDom include it in your project with:

const jsdom = require("jsdom");
const { JSDOM } = jsdom;

or in plain js with:

var jsdom = require("jsdom");
var JSDOM = jsdom.JSDOM;

I hope this is answering your question.

KOsimo
  • 650
  • 6
  • 10
16

To understand the answer, it's necessary to know the relationship of: Javascript Engine, Browser and Node.js.

Javascript Engine: is Javascript compiler which turns JS into machine code. For example, V8, is a great one. Technically V8 is developed in C++ (you can regard it as a C++ program).

V8 implements ECMAScript, which is a standard of Javascript language defining the features and functionalities of JavaScript.

But DOM operation is not defined by ECMAScript. So V8 doesn't support it.

Browser: And developers can use document for DOM operation in browser, because DOM operation is provided by browser, for example: Chrome.

Chrome is also developed by C++ and V8(as mentioned abvoe, which is developed by C++ as well) is embedded into Chrome to interpret Javascript. So Chrome expends or adds features to Javascript by binding JS command and C++ implementation together.

Nodejs: different from the Chrome, it is a server side program. But the same thing is that Nodejs is developed by C++ and V8 is embedded into Nodejs to handle js. Nodejs expands features of Javascript in the similar way with Chrome. But since server side doesn't need to handle DOM, so you can not access such functions inside Nodejs.

Asme Just
  • 1,287
  • 5
  • 27
  • 42
Chris Bao
  • 2,418
  • 8
  • 35
  • 62
2

From the docs just add this comment to the top of your .test.js file to configure your environment:

/**
* @jest-environment jsdom
*/
Weam Adel
  • 151
  • 1
  • 11
0

If you are in React make sure u properly use JSX elements and render without document element. If you need to use document then use

if (typeof window !== 'undefined') { here u can use document. element }

but u cannot use it to render inside because in React conditional render doesn't work

u can use instead:

import Register from './Register'
import { Box, Center } from '@chakra-ui/react'
function App() {
    return (
        <main>
            <Box>
                <Register />
            </Box>
        </main>
    )
}

export default App

where Register is example of element you want to render

-6

OK, shorter answer is you wanna access document Object which is only available in the window and front end side, don't forget that document === window.document which you don't have access in the server and node side...

So never try something like this on your node side for example getting root element by ID which will throw the error, instead try to access it from FrontEnd:

document.getElementById('root');

will throw an Error:

ReferenceError: document is not defined
at Object.<anonymous> (C:\Users\Desktop\app.js:12:50)
at Module._compile (my.js:490:34)
at Object.Module._extensions..js (my.js:518:10)
at Module.load (my.js:555:42)
at Function.Module._load (my.js:610:12)
at Function.Module.runMain (my.js:701:10)
at startup (node.js:899:16)
at node.js:901:3

The short answer is don't use document and window object in node.js as they are not available in node.js...

Using Domino could help in some cases for accessing the dom...

As the name might suggest, domino's goal is to provide a DOM in Node.

In contrast to the original dom.js project, domino was not designed to run untrusted code. Hence it doesn't have to hide its internals behind a proxy facade which makes the code not only simpler, but also more performant.

Domino currently doesn't use any harmony features like proxies or WeakMaps and therefore also runs in older Node versions.

For more info, visit here...

Alireza
  • 100,211
  • 27
  • 269
  • 172
-22
  • "npm install npm -g"
  • after that "npm install -g typescript"

this command helped me for this problem

alexander.polomodov
  • 5,396
  • 14
  • 39
  • 46