7

ERROR ReferenceError: document is not defined

import { readFileSync } from 'fs';
const domino = require('domino');  // import the library `domino`
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString(); // use `index.html` as template
const win = domino.createWindow(template); // create object Window
global['window'] = win;
global['Event'] = win.Event;               // assign the `win.Event` to prop `Event`
global['document'] = win.document;

Even Adding this in Server.ts Fixing Issue But In Performance TTFB Time is Too High. Any Having the Solution...?

2
  • How long is your TTFB? Commented Mar 12, 2020 at 14:07
  • I am getting the same error. Did you get any solution? Commented May 6, 2020 at 14:28

5 Answers 5

19

try to use the DOCUMENT constant provided by the @angular/common package

import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Injectable()
export class MyService {
  constructor(@Inject(DOCUMENT) private document: Document) {}
}
Sign up to request clarification or add additional context in comments.

2 Comments

When accessing this document is document could enough or do you need to replace it with this.document since it becomes a local variable?
Use this.document Please see angular.io/guide/dependency-injection-in-action When localStorage is injected, it is used as this.storage.getItem(key)
6

These globals include window, document, localStorage, indexedDB, setTimeout and setInterval are you can not use in angular universal app

Use document object from Anguar common module

Import from library

import { DOCUMENT } from '@angular/common';

Inject in service

@Inject(DOCUMENT) private document: Document,

Comments

4

Despite its title, it looks like your question is more about slow TTFB than the error with document being undefined.

Regarding that undefined document error, the solution is to:

  • use the following injection @Inject(DOCUMENT) private document if the error appears in your own code

  • use domino if the error appears in 3rd party libraries if you can't replace these libs with other ones that work with angular universal.

To solve the slow TTFB, there is no magic solution. Try to avoid rendering components that do not absolutely need to be rendered server side, make sure you don't have long running API calls, use caching

Comments

1

In the documentation it's stated that: Some common browser APIs and capabilities might not be available on the server. Applications cannot make use of browser-specific global objects like window, document, navigator, or location as well as certain properties of HTMLElement.

In general, code which relies on browser-specific symbols should only be executed in the browser, not on the server. This can be enforced through the afterRender and afterNextRender lifecycle hooks. These are only executed on the browser and skipped on the server.

So your code that relies on browser specific APIs should be moved to afterRender and afterNextRender lifecycle hooks. For example

import { Component, ViewChild, afterNextRender } from '@angular/core';
@Component({
selector: 'my-cmp',
 template: `<span #content>{{ ... }}</span>`,
 })
export class MyComponent {
 @ViewChild('content') contentRef: ElementRef;
  constructor() {
   afterNextRender(() => {
    // Safe to check `scrollHeight` because this will only run in the 
    browser, not the server.
    console.log('content height: ' + 
    this.contentRef.nativeElement.scrollHeight);
});

} }

You could use also afterRender(). You would need to restart your server for the changes to show up

Comments

0

If you have a library that is not compatible with Angular Universal, you should not render this package on the server and you should render it on the client after the response is returned from the server.

isBrowser = false;
constructor(@Inject(PLATFORM_ID) private platformId) {
  this.isBrowser = isPlatformBrowser(this.platformId);
}

now you have to use that package like this:

if (this.isBrowser) {
  ... use package
}

Or you can use ngIf in the html code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.