universal: window is not defined

  • I’m submitting a …
- [ x] bug report
- [ ] feature request
- [ ] support request => Please do not submit support request here, see note at the top of this template.
  • What modules are related to this Issue?
- [ ] aspnetcore-engine
- [x ] express-engine
- [ ] hapi-engine

Node server listening on http://localhost:4000

but when I’m trying to access my localhost:4000 I get this in the console:

ERROR { ReferenceError: window is not defined
    at new e (c:\workspace\proj\dist\server.js:109969:479742)
    at createClass (c:\workspace\proj\dist\server.js:11205:26)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at createRootView (c:\workspace\proj\dist\server.js:12366:5)
    at Object.createProdRootView [as createRootView] (c:\workspace\proj\dist\server.js:13051:12)
    at ComponentFactory_.create (c:\workspace\proj\dist\server.js:10138:46)
    at ComponentFactoryBoundToModule.create (c:\workspace\proj\dist\server.js:3607:29)
    at ApplicationRef_.bootstrap (c:\workspace\proj\dist\server.js:5042:57)
    at c:\workspace\proj\dist\server.js:4820:81
  __zone_symbol__currentTask: 
   ZoneTask {
     _zone: 
      Zone {
        _properties: [Object],
        _parent: [Object],
        _name: 'angular',
        _zoneDelegate: [Object] },
     runCount: 0,
     _zoneDelegates: null,
     _state: 'notScheduled',
     type: 'microTask',
     source: 'Promise.then',
     data: undefined,
     scheduleFn: undefined,
     cancelFn: null,
     callback: [Function],
     invoke: [Function] } }
ERROR { Error: Uncaught (in promise): ReferenceError: FB is not defined
ReferenceError: FB is not defined
    at FacebookService.init (c:\workspace\proj\dist\server.js:48421:36)
    at new e (c:\workspace\proj\dist\server.js:109969:16176)
    at _createClass (c:\workspace\proj\dist\server.js:9798:17)
    at _createProviderInstance$1 (c:\workspace\proj\dist\server.js:9766:26)
    at resolveNgModuleDep (c:\workspace\proj\dist\server.js:9751:17)
    at NgModuleRef_.get (c:\workspace\proj\dist\server.js:10843:16)
    at resolveDep (c:\workspace\proj\dist\server.js:11346:45)
    at createClass (c:\workspace\proj\dist\server.js:11205:35)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at resolvePromise (c:\workspace\proj\dist\server.js:68637:31)
    at resolvePromise (c:\workspace\proj\dist\server.js:68608:17)
    at c:\workspace\proj\dist\server.js:68686:17
    at ZoneDelegate.invokeTask (c:\workspace\proj\dist\server.js:68267:31)
    at Object.onInvokeTask (c:\workspace\proj\dist\server.js:4155:33)
    at ZoneDelegate.invokeTask (c:\workspace\proj\dist\server.js:68266:36)
    at Zone.runTask (c:\workspace\proj\dist\server.js:68034:47)
    at drainMicroTaskQueue (c:\workspace\proj\dist\server.js:68444:35)
    at ZoneTask.invokeTask (c:\workspace\proj\dist\server.js:68345:21)
    at Server.ZoneTask.invoke (c:\workspace\proj\dist\server.js:68330:48)
  rejection: 
   { ReferenceError: FB is not defined
       at FacebookService.init (c:\workspace\proj\dist\server.js:48421:36)
       at new e (c:\workspace\proj\dist\server.js:109969:16176)
       at _createClass (c:\workspace\proj\dist\server.js:9798:17)
       at _createProviderInstance$1 (c:\workspace\proj\dist\server.js:9766:26)
       at resolveNgModuleDep (c:\workspace\proj\dist\server.js:9751:17)
       at NgModuleRef_.get (c:\workspace\proj\dist\server.js:10843:16)
       at resolveDep (c:\workspace\proj\dist\server.js:11346:45)
       at createClass (c:\workspace\proj\dist\server.js:11205:35)
       at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
       at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
     __zone_symbol__currentTask: 
      ZoneTask {
        _zone: [Object],
        runCount: 0,
        _zoneDelegates: null,
        _state: 'notScheduled',
        type: 'microTask',
        source: 'Promise.then',
        data: undefined,
        scheduleFn: undefined,
        cancelFn: null,
        callback: [Function],
        invoke: [Function] } },
  promise: 
   ZoneAwarePromise {
     __zone_symbol__state: 0,
     __zone_symbol__value: 
      { ReferenceError: FB is not defined
          at FacebookService.init (c:\workspace\proj\dist\server.js:48421:36)
          at new e (c:\workspace\proj\dist\server.js:109969:16176)
          at _createClass (c:\workspace\proj\dist\server.js:9798:17)
          at _createProviderInstance$1 (c:\workspace\proj\dist\server.js:9766:26)
          at resolveNgModuleDep (c:\workspace\proj\dist\server.js:9751:17)
          at NgModuleRef_.get (c:\workspace\proj\dist\server.js:10843:16)
          at resolveDep (c:\workspace\proj\dist\server.js:11346:45)
          at createClass (c:\workspace\proj\dist\server.js:11205:35)
          at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
          at createViewNodes (c:\workspace\proj\dist\server.js:12471:49) __zone_symbol__currentTask: [Object] } },
  zone: 
   Zone {
     _properties: { isAngularZone: true },
     _parent: 
      Zone {
        _properties: {},
        _parent: null,
        _name: '<root>',
        _zoneDelegate: [Object] },
     _name: 'angular',
     _zoneDelegate: 
      ZoneDelegate {
        _taskCounts: [Object],
        zone: [Circular],
        _parentDelegate: [Object],
        _forkZS: null,
        _forkDlgt: null,
        _forkCurrZone: [Object],
        _interceptZS: null,
        _interceptDlgt: null,
        _interceptCurrZone: [Object],
        _invokeZS: [Object],
        _invokeDlgt: [Object],
        _invokeCurrZone: [Circular],
        _handleErrorZS: [Object],
        _handleErrorDlgt: [Object],
        _handleErrorCurrZone: [Circular],
        _scheduleTaskZS: [Object],
        _scheduleTaskDlgt: [Object],
        _scheduleTaskCurrZone: [Circular],
        _invokeTaskZS: [Object],
        _invokeTaskDlgt: [Object],
        _invokeTaskCurrZone: [Circular],
        _cancelTaskZS: [Object],
        _cancelTaskDlgt: [Object],
        _cancelTaskCurrZone: [Circular],
        _hasTaskZS: [Object],
        _hasTaskDlgt: [Object],
        _hasTaskDlgtOwner: [Circular],
        _hasTaskCurrZone: [Circular] } },
  task: 
   ZoneTask {
     _zone: 
      Zone {
        _properties: [Object],
        _parent: [Object],
        _name: 'angular',
        _zoneDelegate: [Object] },
     runCount: 0,
     _zoneDelegates: null,
     _state: 'notScheduled',
     type: 'microTask',
     source: 'Promise.then',
     data: undefined,
     scheduleFn: undefined,
     cancelFn: null,
     callback: [Function],
     invoke: [Function] } }
Unhandled Promise rejection: window is not defined ; Zone: <root> ; Task: Promise.then ; Value: { ReferenceError: window is not defined
    at new e (c:\workspace\proj\dist\server.js:109969:479742)
    at createClass (c:\workspace\proj\dist\server.js:11205:26)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at createRootView (c:\workspace\proj\dist\server.js:12366:5)
    at Object.createProdRootView [as createRootView] (c:\workspace\proj\dist\server.js:13051:12)
    at ComponentFactory_.create (c:\workspace\proj\dist\server.js:10138:46)
    at ComponentFactoryBoundToModule.create (c:\workspace\proj\dist\server.js:3607:29)
    at ApplicationRef_.bootstrap (c:\workspace\proj\dist\server.js:5042:57)
    at c:\workspace\proj\dist\server.js:4820:81
  __zone_symbol__currentTask: 
   ZoneTask {
     _zone: 
      Zone {
        _properties: {},
        _parent: null,
        _name: '<root>',
        _zoneDelegate: [Object] },
     runCount: 0,
     _zoneDelegates: null,
     _state: 'notScheduled',
     type: 'microTask',
     source: 'Promise.then',
     data: undefined,
     scheduleFn: undefined,
     cancelFn: null,
     callback: [Function],
     invoke: [Function] } } ReferenceError: window is not defined
    at new e (c:\workspace\proj\dist\server.js:109969:479742)
    at createClass (c:\workspace\proj\dist\server.js:11205:26)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at createRootView (c:\workspace\proj\dist\server.js:12366:5)
    at Object.createProdRootView [as createRootView] (c:\workspace\proj\dist\server.js:13051:12)
    at ComponentFactory_.create (c:\workspace\proj\dist\server.js:10138:46)
    at ComponentFactoryBoundToModule.create (c:\workspace\proj\dist\server.js:3607:29)
    at ApplicationRef_.bootstrap (c:\workspace\proj\dist\server.js:5042:57)
    at c:\workspace\proj\dist\server.js:4820:81
ERROR { ReferenceError: window is not defined
    at new e (c:\workspace\proj\dist\server.js:109969:479742)
    at createClass (c:\workspace\proj\dist\server.js:11205:26)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at createRootView (c:\workspace\proj\dist\server.js:12366:5)
    at Object.createProdRootView [as createRootView] (c:\workspace\proj\dist\server.js:13051:12)
    at ComponentFactory_.create (c:\workspace\proj\dist\server.js:10138:46)
    at ComponentFactoryBoundToModule.create (c:\workspace\proj\dist\server.js:3607:29)
    at ApplicationRef_.bootstrap (c:\workspace\proj\dist\server.js:5042:57)
    at c:\workspace\proj\dist\server.js:4820:81
  __zone_symbol__currentTask: 
   ZoneTask {
     _zone: 
      Zone {
        _properties: [Object],
        _parent: [Object],
        _name: 'angular',
        _zoneDelegate: [Object] },
     runCount: 0,
     _zoneDelegates: null,
     _state: 'notScheduled',
     type: 'microTask',
     source: 'Promise.then',
     data: undefined,
     scheduleFn: undefined,
     cancelFn: null,
     callback: [Function],
     invoke: [Function] } }
ERROR { Error: Uncaught (in promise): ReferenceError: FB is not defined
ReferenceError: FB is not defined
    at FacebookService.init (c:\workspace\proj\dist\server.js:48421:36)
    at new e (c:\workspace\proj\dist\server.js:109969:16176)
    at _createClass (c:\workspace\proj\dist\server.js:9798:17)
    at _createProviderInstance$1 (c:\workspace\proj\dist\server.js:9766:26)
    at resolveNgModuleDep (c:\workspace\proj\dist\server.js:9751:17)
    at NgModuleRef_.get (c:\workspace\proj\dist\server.js:10843:16)
    at resolveDep (c:\workspace\proj\dist\server.js:11346:45)
    at createClass (c:\workspace\proj\dist\server.js:11205:35)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at resolvePromise (c:\workspace\proj\dist\server.js:68637:31)
    at resolvePromise (c:\workspace\proj\dist\server.js:68608:17)
    at c:\workspace\proj\dist\server.js:68686:17
    at ZoneDelegate.invokeTask (c:\workspace\proj\dist\server.js:68267:31)
    at Object.onInvokeTask (c:\workspace\proj\dist\server.js:4155:33)
    at ZoneDelegate.invokeTask (c:\workspace\proj\dist\server.js:68266:36)
    at Zone.runTask (c:\workspace\proj\dist\server.js:68034:47)
    at drainMicroTaskQueue (c:\workspace\proj\dist\server.js:68444:35)
    at ZoneTask.invokeTask (c:\workspace\proj\dist\server.js:68345:21)
    at Server.ZoneTask.invoke (c:\workspace\proj\dist\server.js:68330:48)
  rejection: 
   { ReferenceError: FB is not defined
       at FacebookService.init (c:\workspace\proj\dist\server.js:48421:36)
       at new e (c:\workspace\proj\dist\server.js:109969:16176)
       at _createClass (c:\workspace\proj\dist\server.js:9798:17)
       at _createProviderInstance$1 (c:\workspace\proj\dist\server.js:9766:26)
       at resolveNgModuleDep (c:\workspace\proj\dist\server.js:9751:17)
       at NgModuleRef_.get (c:\workspace\proj\dist\server.js:10843:16)
       at resolveDep (c:\workspace\proj\dist\server.js:11346:45)
       at createClass (c:\workspace\proj\dist\server.js:11205:35)
       at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
       at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
     __zone_symbol__currentTask: 
      ZoneTask {
        _zone: [Object],
        runCount: 0,
        _zoneDelegates: null,
        _state: 'notScheduled',
        type: 'microTask',
        source: 'Promise.then',
        data: undefined,
        scheduleFn: undefined,
        cancelFn: null,
        callback: [Function],
        invoke: [Function] } },
  promise: 
   ZoneAwarePromise {
     __zone_symbol__state: 0,
     __zone_symbol__value: 
      { ReferenceError: FB is not defined
          at FacebookService.init (c:\workspace\proj\dist\server.js:48421:36)
          at new e (c:\workspace\proj\dist\server.js:109969:16176)
          at _createClass (c:\workspace\proj\dist\server.js:9798:17)
          at _createProviderInstance$1 (c:\workspace\proj\dist\server.js:9766:26)
          at resolveNgModuleDep (c:\workspace\proj\dist\server.js:9751:17)
          at NgModuleRef_.get (c:\workspace\proj\dist\server.js:10843:16)
          at resolveDep (c:\workspace\proj\dist\server.js:11346:45)
          at createClass (c:\workspace\proj\dist\server.js:11205:35)
          at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
          at createViewNodes (c:\workspace\proj\dist\server.js:12471:49) __zone_symbol__currentTask: [Object] } },
  zone: 
   Zone {
     _properties: { isAngularZone: true },
     _parent: 
      Zone {
        _properties: {},
        _parent: null,
        _name: '<root>',
        _zoneDelegate: [Object] },
     _name: 'angular',
     _zoneDelegate: 
      ZoneDelegate {
        _taskCounts: [Object],
        zone: [Circular],
        _parentDelegate: [Object],
        _forkZS: null,
        _forkDlgt: null,
        _forkCurrZone: [Object],
        _interceptZS: null,
        _interceptDlgt: null,
        _interceptCurrZone: [Object],
        _invokeZS: [Object],
        _invokeDlgt: [Object],
        _invokeCurrZone: [Circular],
        _handleErrorZS: [Object],
        _handleErrorDlgt: [Object],
        _handleErrorCurrZone: [Circular],
        _scheduleTaskZS: [Object],
        _scheduleTaskDlgt: [Object],
        _scheduleTaskCurrZone: [Circular],
        _invokeTaskZS: [Object],
        _invokeTaskDlgt: [Object],
        _invokeTaskCurrZone: [Circular],
        _cancelTaskZS: [Object],
        _cancelTaskDlgt: [Object],
        _cancelTaskCurrZone: [Circular],
        _hasTaskZS: [Object],
        _hasTaskDlgt: [Object],
        _hasTaskDlgtOwner: [Circular],
        _hasTaskCurrZone: [Circular] } },
  task: 
   ZoneTask {
     _zone: 
      Zone {
        _properties: [Object],
        _parent: [Object],
        _name: 'angular',
        _zoneDelegate: [Object] },
     runCount: 0,
     _zoneDelegates: null,
     _state: 'notScheduled',
     type: 'microTask',
     source: 'Promise.then',
     data: undefined,
     scheduleFn: undefined,
     cancelFn: null,
     callback: [Function],
     invoke: [Function] } }
Unhandled Promise rejection: window is not defined ; Zone: <root> ; Task: Promise.then ; Value: { ReferenceError: window is not defined
    at new e (c:\workspace\proj\dist\server.js:109969:479742)
    at createClass (c:\workspace\proj\dist\server.js:11205:26)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at createRootView (c:\workspace\proj\dist\server.js:12366:5)
    at Object.createProdRootView [as createRootView] (c:\workspace\proj\dist\server.js:13051:12)
    at ComponentFactory_.create (c:\workspace\proj\dist\server.js:10138:46)
    at ComponentFactoryBoundToModule.create (c:\workspace\proj\dist\server.js:3607:29)
    at ApplicationRef_.bootstrap (c:\workspace\proj\dist\server.js:5042:57)
    at c:\workspace\proj\dist\server.js:4820:81
  __zone_symbol__currentTask: 
   ZoneTask {
     _zone: 
      Zone {
        _properties: {},
        _parent: null,
        _name: '<root>',
        _zoneDelegate: [Object] },
     runCount: 0,
     _zoneDelegates: null,
     _state: 'notScheduled',
     type: 'microTask',
     source: 'Promise.then',
     data: undefined,
     scheduleFn: undefined,
     cancelFn: null,
     callback: [Function],
     invoke: [Function] } } ReferenceError: window is not defined
    at new e (c:\workspace\proj\dist\server.js:109969:479742)
    at createClass (c:\workspace\proj\dist\server.js:11205:26)
    at createDirectiveInstance (c:\workspace\proj\dist\server.js:11030:37)
    at createViewNodes (c:\workspace\proj\dist\server.js:12471:49)
    at createRootView (c:\workspace\proj\dist\server.js:12366:5)
    at Object.createProdRootView [as createRootView] (c:\workspace\proj\dist\server.js:13051:12)
    at ComponentFactory_.create (c:\workspace\proj\dist\server.js:10138:46)
    at ComponentFactoryBoundToModule.create (c:\workspace\proj\dist\server.js:3607:29)
    at ApplicationRef_.bootstrap (c:\workspace\proj\dist\server.js:5042:57)
    at c:\workspace\proj\dist\server.js:4820:81

  • What is the expected behavior? Should access my angular project instead throwing an error

  • What is the motivation / use case for changing the behavior? bug fix

  • Please tell us about your environment:

  • Angular version: 4.0.0
  • Browser: all
  • Language:all
  • OS: Windows
  • Platform:NodeJS
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 57 (1 by maintainers)

Most upvoted comments

You can fix window is not defined like this: server.ts (start of file)

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;

look: https://github.com/Angular-RU/angular-universal-starter/blob/master/server.ts

“window is not defined” came from 3rd party library which accessing window variable.

You should wrapping your code with browser check condition

In html,

<ng-container *ngIf="isBrowser">
   <!-- In my case, ngx-siema & ngx-slcik -->
   <ngx-siema></ngx-siema> 
</ng-container>

In ts,

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

...

if (this.isBrowser) { 
  // put your code which is access window variable 
} 

I’ve found a workaround to fix the issue by adding "module": "commonjs" to "compilerOptions" of tsconfig.server.json. It seems this is a configuration of Angular Universal 8. Yet, I’ve got it working on v9 and v10. Note that we still need domino workaround. Hope this helps.

For more info: https://angular.io/guide/migration-update-module-and-target-compiler-options

@wattachai you are a life saver, I finally got it working on Angular 11 with Ivy (I had a problem using firebaseui, which depends on the window). Two main points for anyone stumbling on this:

  • add “module”: “commonjs” to “compilerOptions” of tsconfig.server.json
  • mock window, document and everything you need BEFORE import { AppServerModule } from ‘./src/main.server’;

Here’s my package.json, tsconfig.server.ts and server.ts for who may need a reference

package.json

{
  "name": "@nbinar/app",
  "scripts": {
    "ng": "ng",
    "start": "concurrently \"npm run build:shared:watch\" \"ng run nbinar:serve --hmr\" \"npm run build:functions:watch\" \"npm run fb:start\"",
    "start:server:dev": "ng run nbinar:serve-ssr",
    "build:dev": "NODE_ENV=production ng run nbinar:build:dev",
    "build:prod": "NODE_ENV=production ng run nbinar:build:production",
    "build:server:dev": "NODE_ENV=production ng run nbinar:server:dev",
    "build:server:prod": "NODE_ENV=production ng run nbinar:server:production",
    "build:functions": "npm run --prefix functions build",
    "build:functions:watch": "npm run --prefix functions build:watch",
    "build:shared": "npm run --prefix shared build",
    "build:shared:watch": "npm run --prefix shared build:watch",
    "build:all:dev": "npm run build:shared && npm run build:dev && npm run build:server:dev && npm run build:functions",
    "deploy": "rm -rf dist/nbinar/browser/index.html && firebase deploy",
    "test": "ng test",
    "lint": "eslint --color \"src/**/*.ts\"",
    "lint:fix": "npm run lint -- --fix",
    "e2e": "ng e2e",
    "serve:ssr": "node dist/nbinar/server/main.js",
    "prerender": "ng run nbinar:prerender",
    "fb:start": "firebase emulators:start --only=firestore,functions,pubsub,auth --import=./firestore-data --export-on-exit=./firestore-data",
    "firebase": "firebase"
  },
  "dependencies": {
    "@angular/animations": "^11.0.5",
    "@angular/common": "^11.0.5",
    "@angular/compiler": "^11.0.5",
    "@angular/core": "^11.0.5",
    "@angular/fire": "^6.1.2",
    "@angular/forms": "^11.0.5",
    "@angular/platform-browser": "^11.0.5",
    "@angular/platform-browser-dynamic": "^11.0.5",
    "@angular/platform-server": "^11.0.5",
    "@angular/router": "^11.0.5",
    "@nbinar/shared": "file:shared",
    "algoliasearch": "^3.35.1",
    "angular-instantsearch": "^3.0.0-beta.5",
    "angular-svg-icon": "^11.0.0",
    "firebase": "^8.2.1",
    "firebaseui": "^4.7.1",
    "firebaseui-angular": "^5.1.1",
    "instantsearch.js": "^3.7.0",
    "ngx-logger": "^4.1.9",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.5",
    "@angular/cli": "^11.0.5",
    "@angular/compiler-cli": "^11.0.5",
    "@garygrossgarten/ngx-tailwind": "^0.4.0",
    "@nguniversal/builders": "^11.0.1",
    "@nguniversal/express-engine": "^11.0.1",
    "@types/algoliasearch": "^3.34.11",
    "@types/express": "^4.17.0",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "@typescript-eslint/eslint-plugin": "^4.4.0",
    "@typescript-eslint/parser": "^4.4.0",
    "bufferutil": "^4.0.1",
    "codelyzer": "^6.0.0",
    "concurrently": "^5.3.0",
    "domino": "^2.1.6",
    "eslint": "^7.11.0",
    "eslint-config-prettier": "^6.12.0",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-prettier": "^3.1.4",
    "express": "^4.17.1",
    "firebase-tools": "^8.16.2",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.1",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "ngx-build-plus": "^11.0.0",
    "postcss-import": "^12.0.1",
    "postcss-loader": "^4.0.4",
    "postcss-scss": "^3.0.2",
    "prettier": "^2.1.2",
    "protractor": "~7.0.0",
    "tailwindcss": "^1.9.6",
    "ts-node": "~8.3.0",
    "typescript": "~4.0.2",
    "utf-8-validate": "^5.0.2",
    "ws": "^7.3.1",
    "xhr2": "^0.2.0"
  }
}

tsconfig.server.ts

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "outDir": "./out-tsc/server",
    "target": "es2016",
    "types": [
      "node"
    ],
    "module": "commonjs"
  },
  "files": [
    "src/main.server.ts",
    "server.ts"
  ],
  "angularCompilerOptions": {
    "entryModule": "./src/app/app.server.module#AppServerModule"
  }
}

server.ts

// These are important and needed before anything else
import 'zone.js/dist/zone-node';

import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { APP_BASE_HREF } from '@angular/common';
import { readFileSync } from 'fs';
import { createWindow } from 'domino';

const distFolder = join(process.cwd(), 'dist/nbinar/browser');
const indexHtml = 'index.html';
const template = readFileSync(join(distFolder, indexHtml)).toString();
const win = createWindow(template);

// Polyfills
(global as any).WebSocket = require('ws');
(global as any).XMLHttpRequest = require('xhr2');
(global as any).window = win;
(global as any).document = win.document;

// needs to be after window definition
import { AppServerModule } from './src/main.server';

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
  const server = express();

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
  server.engine('html', (_, options: { req: any }, callback) => {
    const engine = ngExpressEngine({
      bootstrap: AppServerModule,
      providers: [
        { provide: 'request', useFactory: () => options.req as any, deps: [] },
      ],
    });
    engine(_, options, callback);
  });

  server.set('view engine', 'html');
  server.set('views', distFolder);

  // Example Express Rest API endpoints
  // server.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get(
    '*.*',
    express.static(distFolder, {
      maxAge: '1y',
    }),
  );

  // All regular routes use the Universal engine
  server.get('*', (req, res) => {
    res.render(indexHtml, {
      req,
      providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
    });
  });

  return server;
}

function run(): void {
  if (!process.env.FUNCTION_NAME) {
    const port = process.env.PORT || 4000;

    // Start up the Node server
    const server = app();
    server.listen(port, () => {
      console.log(`Node Express server listening on http://localhost:${port}`);
    });
  } else {
    console.log(`Running in cloud functions environment`);
  }
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = (mainModule && mainModule.filename) || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
  run();
}

export * from './src/main.server';

this may or may not help someone so ill post in case it does. i had some strange issues when using const domino = require('domino'). i was missing methods on some objects. to resolve this, i referenced the module that gets bundled within platform-server

const domino = require('@angular/platform-server/node_modules/domino');

const domino = require('@angular/platform-server/node_modules/domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(getTemplatesPath(), 'index.html')).toString();
const win = domino.createWindow(template);

global['window'] = win;
global['document'] = win.document;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;
global['MutationObserver'] = getMockMutationObserver();

function getMockMutationObserver() {
  return class {
    observe(node, options) {
    }
    disconnect() {
    }
    takeRecords() {
      return [];
    }
  };
}

not entirely sure why the two references were different but there you go

@kenji-1996 Good point. the best way to support material2 with ssr is import hammerjs in main.ts

Material guide already said hammerjs should be imported from main.ts (not polyfills.ts or app.module) https://github.com/angular/material2/blob/master/guides/getting-started.md

After installing, import it on your app’s entry point (e.g. src/main.ts).

@nimatullah You should put

const domino = require("domino");
const win = domino.createWindow(template);
global["window"] = win;
global["document"] = win.document;

before

const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./web/server/main');

Just want to jump in here and say that I had ‘hammerjs’ imported for Material2 and that was what was giving this issue, removing that (or adding checks for when its in browser) fixed this

With the latest answers, I’ve had navigator is not defined, which has an easy fix (global as any).navigator = win.navigator;.

Later, TypeError: Cannot read property 'charAt' of undefined popped up. It was doable to have it fixed by removing(global as any).XMLHttpRequest = require('xhr2');

Apparently, the xhr2 and ws packages weren’t needed, and the code could’ve been dropped as well

(global as any).WebSocket = require('ws');
(global as any).XMLHttpRequest = require('xhr2');

I’ve also simplified this part

const distFolder = join(process.cwd(), 'dist/nbinar/browser');
const indexHtml = 'index.html';
const template = readFileSync(join(distFolder, indexHtml)).toString();
const win = createWindow(template);

into

const indexHtml = join(
  process.cwd(),
  'dist/nbinar/browser/index2.html'
);
const win = createWindow(indexHtml);

It left me with the whole code as lean as possible

import { createWindow } from 'domino';
import { join } from 'path';
const indexHtml = join(
  process.cwd(),
  'dist/nbinar/browser/index2.html'
);
const win = createWindow(indexHtml);

// Polyfills
(global as any).window = win;
(global as any).document = win.document;
(global as any).navigator = win.navigator;

All in server.ts, other files were completely fine. Of course, I’ve excluded the 3 useless packages from package.json, i.e. fs, xhr2, and ws.

Many thanks for contribution to fixing such an irritating error.

PS. Works fine on Angular 10, locally rendered by Cloud Functions for Firebase as well as once deploying to Firebase.

Looks like I’m not the only one who has noticed regression after upgrading to Angular 10 (from Angular 8). There are quite some issues open related to that version of Angular/Universal such as #1675 #1835

Is it maybe related to the fact that webpack.server.config.js is no longer needed and how the builders in angular.json have changed?

this may or may not help someone so ill post in case it does. i had some strange issues when using const domino = require('domino'). i was missing methods on some objects. to resolve this, i referenced the module that gets bundled within platform-server

const domino = require('@angular/platform-server/node_modules/domino');

const domino = require('@angular/platform-server/node_modules/domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(getTemplatesPath(), 'index.html')).toString();
const win = domino.createWindow(template);

global['window'] = win;
global['document'] = win.document;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;
global['MutationObserver'] = getMockMutationObserver();

function getMockMutationObserver() {
  return class {
    observe(node, options) {
    }
    disconnect() {
    }
    takeRecords() {
      return [];
    }
  };
}

not entirely sure why the two references were different but there you go

this way helped me with angular 8 and the webpack build. All is working fine with this solution…

BUT after upgrading to Angular 9 including Angular Universal, Angular CLI (and much more) and using the new Build-Tool Ivy, i am getting window is not defined again.

could anyone help me out?

My Server.ts is looking like this:

import { APP_BASE_HREF } from '@angular/common';
import { ngExpressEngine } from '@nguniversal/express-engine';
import compression from 'compression';
import express from 'express';
import { existsSync } from 'fs';
import { join } from 'path';
// tslint:disable-next-line:no-submodule-imports
import 'zone.js/dist/zone-node';

import { AppServerModule } from './src/main.server';

// tslint:disable:no-any no-console
const domino = require('domino');
const fs = require('fs');
const path = require('path');

/**
 * global variables
 */
const PORT: number = process.env.PORT && parseInt(process.env.PORT) || 4000;
const DIST_FOLDER = join(process.cwd(), 'www');

/**
 * Manipulate index.html
 */
const template = fs.readFileSync(path.join(DIST_FOLDER, 'index.html')).toString();

/**
 * Set Frontend Globals to prevent errors
 */
const win = domino.createWindow(template);
(global as any)['window'] = win;
(global as any)['KeyboardEvent'] = win.KeyboardEvent;
(global as any)['HTMLInputElement'] = win.HTMLInputElement;
(global as any)['MouseEvent'] = win.MouseEvent;
(global as any)['Event'] = win.Event;
(global as any)['document'] = win.document;
(global as any)['navigator'] = win.navigator;
(global as any)['FormData'] = win.FormData;

.......

EDITED: INFO: #1678 this helped me with this issue…

You can fix window is not defined like this: server.ts (start of file)

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;

look: https://github.com/Angular-RU/angular-universal-starter/blob/master/server.ts

Please help I tried to solve window issue as you mention then i get this error… … throw err; ^

Error: ENOENT: no such file or directory, open ‘\dist\index.html’ … As my index.html is in dist/browser so i tried to do it like const template = fs.readFileSync(path.join(__dirname, ‘.’, ‘dist/browser’, ‘index.html’)).toString();

still got this error fs.js:114 throw err; ^

Error: ENOENT: no such file or directory, open ‘\dist\index.html’

I also tried these solutions (mock window in server.ts and implemented my buffer as MyBlob) but now I have this error as follows:

` var workerUrl = URL.createObjectURL(blob); ^ TypeError: Cannot read property ‘createObjectURL’ of undefined

   at module.exports (..\dist\server.js:138069:37)
at ..\dist\server.js:138078:30
at Object../node_modules/aws-amplify-angular/dist/src/components/interactions/chatbot/aws-lex-audio.js.5../worker.js (..\dist\server.js:138226:15)
at s (..\dist\server.js:137616:13)
at ..\dist\server.js:137616:71
at ..\dist\server.js:137621:27
at Object../node_modules/aws-amplify-angular/dist/src/components/interactions/chatbot/aws-lex-audio.js.1../recorder.js (..\dist\server.js:137826:15)
at s (..\dist\server.js:137616:13)
at ..\dist\server.js:137616:71
at Object.<anonymous> (..\dist\server.js:137999:48)

` Any solution?

@andrew273 did you figure it out ?

Hey all!

As this is a common issue, we’ve released some helper methods & directives (more to come soon! SEO-helpers/etc) available at:

@trilon/ng-universal


Ability to mock window/document that are extendable (incase you need to add additional properties)

<ng-container *isBrowser> (and *isServer) helper Directives

More to come soon!

@danieldanielecki @michelepatrassi, after several hours and tests done, I almost gave up, but thanks to your answers I was able to compile my project in Angular Universal.

this is my config:

image

this issue delaying our production release by week now, anyone might have encountered on angular 10 (we have implemented domino and tried all sorts of placements of configurations)

Window not defined, caused by keycloak-js

if that polyfill isnt working you might just need to implement Blob yourself using a Buffer in node.

class MyBlob {
  type: string;
  private buffer;

  constructor(blobParts, options) {
    this.buffer = Buffer.from(blobParts);
    this.type = options.type;
  }
 
  get size() {
    return this.buffer.length;
  }

  slice(start, end, contentType) {
    this.buffer.slice(start, end);
  }
}

global.Blob = MyBlob;

const blob = new Blob('foo bar baz', {type: 'application/json'});
console.log(blob.size);
console.log(blob.type)

I have solved the Window error but I am getting this error now, can anyone help?

var blob = new Blob([src], { type: 'text/javascript' });
ReferenceError: Blob is not defined
    at module.exports (..\dist\server.js:207664:28)
    at ..dist\server.js:207677:30
    at Object.module.exports../node_modules/aws-amplify-angular/dist/src/components/interactions/chatbot/aws-lex-audio.js.5../worker.js (..\dist\server.js:207825:15)
    at s (..dist\server.js:207215:13)
    at ..\dist\server.js:207215:71
    at ..\dist\server.js:207220:27
    at Object.module.exports../node_modules/aws-amplify-angular/dist/src/components/interactions/chatbot/aws-lex-audio.js.1../recorder.js (..\dist\server.js:207425:15)
    at s (..\dist\server.js:207215:13)
    at ..\dist\server.js:207215:71
    at Object.<anonymous> (..\dist\server.js:207598:48)

I’ve added

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync('./dist/browser/index.html').toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;

but this gives an error:

TypeError: Cannot read property 'stringify' of undefined
    at Module.<anonymous> (/Users/louis/codes/angar/dist/server.js:194863:308)
    at __webpack_require__ (/Users/louis/codes/angar/dist/server.js:20:30)
    at Module.<anonymous> (/Users/louis/codes/angar/dist/server.js:173495:86)
    at __webpack_require__ (/Users/louis/codes/angar/dist/server.js:20:30)
    at Module.<anonymous> (/Users/louis/codes/angar/dist/server.js:173465:77)
    at __webpack_require__ (/Users/louis/codes/angar/dist/server.js:20:30)
    at Module.<anonymous> (/Users/louis/codes/angar/dist/server.js:173425:76)
    at __webpack_require__ (/Users/louis/codes/angar/dist/server.js:20:30)
    at Module.<anonymous> (/Users/louis/codes/angar/dist/server.js:173052:75)
    at __webpack_require__ (/Users/louis/codes/angar/dist/server.js:20:30)

To anyone recommending to have the browser get mocked with lines like…

import { createWindow } from 'domino';
const win: any = createWindow(template);

global['document'] = win.document;

there may be unexpected effects that break server side rendering. I’ve just spent many many hours tracking down a server side prerendering bug with the AngularFire2 Database Observable not emiting anything at all.

Since it the Observable was working with ng serve --prod, I was focused on either the webpack traspilation process or a possible firewall on websocket for node. Although for some reason uncommenting out the line:

global['document'] = win.document;

allowed the angularfire2 observable to emit properly again. I’m not sure why it does this, but I felt it was important to point this out if anyone relies on angularfire2 observables emiting data for server side rendering.

@Ks89 in https://github.com/Angular-RU/angular-universal-starter/blob/master/server.ts line 94:

app.get('*', (req, res) => {
  global['navigator'] = req['headers']['user-agent'];