Search code examples
angularangular-universal

Angular - ReferenceError: Document is not defined while using Inject


When importing a module into the AppModule that has a component that injects Document, the following errors appears after compiling.

Compiled successfully.
/Users/dev/repo/dist/apps/project/server/main.js:15727
        Document,
        ^

ReferenceError: Document is not defined
    at Module.98165 (/Users/dev/repo/dist/apps/project/server/main.js:15727:9)
    at __webpack_require__ (/Users/dev/repo/dist/apps/project/server/main.js:304224:42)
    at Module.54694 (/Users/dev/repo/dist/apps/project/server/main.js:15506:99)
    at __webpack_require__ (/Users/dev/repo/dist/apps/project/server/main.js:304224:42)
    at Module.26162 (/Users/dev/repo/dist/apps/project/server/main.js:159:97)
    at __webpack_require__ (/Users/dev/repo/dist/apps/project/server/main.js:304224:42)
    at Module.35739 (/Users/dev/repo/dist/apps/project/server/main.js:328:69)
    at __webpack_require__ (/Users/dev/repo/dist/apps/project/server/main.js:304224:42)
    at /Users/dev/repo/dist/apps/project/server/main.js:304405:84
    at /Users/dev/repo/dist/apps/project/server/main.js:304461:3

A server error has occurred.
node exited with 1 code.
connect ECONNREFUSED 127.0.0.1:64253

This happens for an Angular application using Angular Universal in a Nx workspace.

We have an OverlayComponent that uses Document:

@Component({
  selector: 'app-overlay',
  templateUrl: './overlay.component.html'
})
export class OverlayComponent {
  @Input() public shouldBlockScroll = true;

  constructor(
    private viewportRuler: ViewportRuler,
    @Inject(DOCUMENT) private document: Document
  ) {}

  public open() {
    ...
    const scrollStrategy = this.shouldBlockScroll
      ? new BlockScrollStrategy(this.viewportRuler, this.document)
      : new NoopScrollStrategy();
    ...
  }
}

Then a module that exports this component:

@NgModule({
  imports: [CommonModule],
  declarations: [OverlayComponent],
  exports: [OverlayComponent]
})
export class OverlayModule {}

At this point, if in AppModule we import the OverlayModule, the above error appears.
But if in comparison we Inject the document in the AppComponent, the error does not appear.

Does it have to do something about the order of imports and how they are loaded in SSR?


Solution

  • This seems to be a bug in the Angular Universal Compiler. A workaround is to simply create a custom type and use it:

    type DocumentType = Document
    
    @Inject(DOCUMENT) private document: DocumentType