11

I'm trying to setup SSR on angular 9 project with some third party librairies without success.

Below the error

ReferenceError: window is not defined
at ./node_modules/intl-tel-input/build/js/intlTelInput.js (main.js:295050:32)
at Object../node_modules/intl-tel-input/build/js/intlTelInput.js (main.js:295052:3)
at __webpack_require__ (main.js:20:30)
at Object../node_modules/intl-tel-input/index.js (main.js:296381:18)
at __webpack_require__ (main.js:20:30)
at Module../node_modules/intl-tel-input-ng/__ivy_ngcc__/fesm2015/intl-tel-input-ng.js (main.js:294832:72)
at __webpack_require__ (main.js:20:30)
    at Object.. main.js:463107:29)
    at __webpack_require__ (main.js:20:30)
    at Object.. main.js:462977:33)
A server error has occurred.
node exited with 1 code.
connect ECONNREFUSED 127.0.0.1:50362

I don't have access to window object on the server side, it's normal, so to avoid this error I'm checking the platform and using conditional logic in the components that need intl-tel-input lib ...without success.

How can I fix window, navigator, document error while SSR ?

below package.json file

    {
  "name": "dz",
  "version": "0.0.0",
  "scripts": {

    "compile:server_bak": "webpack --mode production --config webpack.server.config.js --progress --colors",
    "build:ssr_bak": "npm run build:client-and-server-bundles && npm run compile:server",
    "serve:ssr_bak": "node dist/server",
    "build:client-and-server-bundles_bak": "npm run build-prod && ng run dz:server:production",
    "dev:ssr": "ng run dz:serve-ssr",
    "serve:ssr": "node dist/server/main.js",
    "build:ssr": "ng build --prod && ng run dz:server:production",
    "prerender": "ng run dz:prerender"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^9.0.0",
    "@angular/cdk": "^9.0.0",
    "@angular/common": "^9.0.0",
    "@angular/compiler": "^9.0.0",
    "@angular/core": "^9.0.0",
    "@angular/forms": "^9.0.0",
    "@angular/google-maps": "^9.0.0-rc.0",
    "@angular/localize": "^9.0.0-next.5",
    "@angular/material": "^9.0.0",
    "@angular/platform-browser": "^9.0.0",
    "@angular/platform-browser-dynamic": "^9.0.0",
    "@angular/platform-server": "^9.0.0",
    "@angular/pwa": "^0.803.23",
    "@angular/router": "^9.0.0",
    "@angular/service-worker": "^9.0.0",
    "@kolkov/angular-editor": "^1.0.3",
    "@ng-bootstrap/ng-bootstrap": "^5.2.1",
    "@ng-toolkit/universal": "^8.0.3",
    "@nguniversal/common": "~9.0.0",
    "@nguniversal/express-engine": "^9.0.0",
    "@ngx-translate/core": "^11.0.1",
    "@ngx-translate/http-loader": "^4.0.0",
    "@nicky-lenaers/ngx-scroll-to": "^3.0.1",
    "@sentry/browser": "^5.11.1",
    "@smip/ngx-materialize": "^0.3.0",
    "@swimlane/ngx-charts": "^13.0.2",
    "@trilon/ng-universal": "^2.1.0",
    "@types/express": "^4.17.1",
    "@types/lodash": "^4.14.141",
    "acorn": "^7.1.0",
    "angular-calendar": "0.27.9",
    "angular-in-memory-web-api": "~0.9.0",
    "angular-resizable-element": "^3.3.0",
    "angular2-image-upload": "1.0.0-rc.2",
    "body-parser": "^1.19.0",
    "bootstrap": "^4.4.1",
    "calendar-utils": "0.7.0",
    "cookie-parser": "^1.4.4",
    "cookieconsent": "^3.1.1",
    "core-js": "^3.6.4",
    "cors": "~2.8.5",
    "date-fns": "^1.30.1",
    "domino": "^2.1.4",
    "express": "^4.17.1",
    "express-http-proxy": "^1.6.0",
    "font-awesome": "^4.7.0",
    "google-libphonenumber": "^3.2.6",
    "gzip-all": "^1.0.0",
    "imagesloaded": "^4.1.4",
    "intersection-observer": "^0.7.0",
    "intl-tel-input": "16.0.10",
    "intl-tel-input-ng": "0.1.0",
    "materialize-css": "^1.0.0",
    "mock-browser": "^0.92.14",
    "moment": "^2.24.0",
    "ng2-sticky-kit": "^6.1.0",
    "ngx-cookieconsent": "^2.2.3",
    "ngx-google-places-autocomplete": "^2.0.4",
    "ngx-lightbox": "^2.1.0",
    "ngx-moment": "^3.5.0",
    "ngx-pagination": "5.0.0",
    "ngx-progressbar": "^6.0.1",
    "ngx-quicklink": "^0.2.0",
    "ngx-scrollspy": "^1.2.1",
    "path": "^0.12.7",
    "popper.js": "^1.16.1",
    "positioning": "1.4.0",
    "preboot": "^7.0.0",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^6.5.4",
    "rxjs-compat": "^6.5.4",
    "sweetalert2": "^9.7.0",
    "ts-helpers": "^1.1.2",
    "tslib": "^1.10.0",
    "typings": "^2.1.1",
    "webpack": "^4.41.5",
    "workbox-sw": "^4.3.1",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/architect": "^0.900.1",
    "@angular-devkit/build-angular": "^0.900.1",
    "@angular/cli": "^9.0.1",
    "@angular/compiler-cli": "^9.0.0",
    "@angular/language-service": "^9.0.0",
    "@types/jasminewd2": "~2.0.6",
    "@types/jquery": "^3.2.12",
    "firebase-tools": "^6.10.0",
    "fuzzy": "^0.1.3",
    "http-server": "^0.11.1",
    "inquirer": "^6.2.2",
    "inquirer-autocomplete-prompt": "^1.0.1",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.5.1",
    "protractor": "~6.0.0",
    "ts-loader": "^5.4.5",
    "@nguniversal/builders": "^9.0.0",
    "@types/express": "^4.17.0",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.5.0",
    "codelyzer": "^5.1.2",
    "karma": "~4.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~2.1.0",
    "ts-node": "~8.3.0",
    "tslint": "~5.17.0",
    "typescript": "~3.7.5",
    "webpack-cli": "^3.3.10",
    "webpack-node-externals": "^1.7.2"
  },
  "budgets": [
    {
      "type": "initial",
      "maximumWarning": "2mb",
      "maximumError": "5mb"
    }
  ]
}
Franky
  • 902
  • 2
  • 11
  • 28
  • 1
    Did you ever fix this? I have the problem as well. Wasn't an issue in Angular 8 even with SSR. – WillyC May 11 '20 at 18:34

4 Answers4

2

If you have mutiple components where you need window to be used. There is one more way to fix this error, where you need not to import or install any third party package.

Reason of this error is, while excuting or parsing the code at node server, window is not defined. So, to avoid that we can put if condition like this if (isPlatformBrowser(this.platformId)) which will be executed only when the script is running at browser level

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


@Component({
  selector: 'space-app',
  templateUrl: './app.component.html'
})

export class AppComponent {

  constructor(
    @Inject(PLATFORM_ID) private platformId: any
  ) { }

  ngOnInit() {}

  onActivate() {
    if (isPlatformBrowser(this.platformId)) {
      window.scrollTo(0, 0);
    }
  }
}

This is for the places where you will be using window directly. But what if any third party angular package is using window that you aren't aware of. To prevent errors from those cases. We need to add a piece of code in server.ts

const path = require('path');
const domino = require('domino');
const templateA = fs.readFileSync(path.join('dist/browser', 'index.html')).toString();
const win = domino.createWindow(templateA);

global['window'] = win;
global['document'] = win.document;
// Express server
export const app = express();

But make sure the position of export const app = express() is correct

Abhishek Tripathi
  • 1,570
  • 3
  • 20
  • 32
2

I declared this at the top of my server.ts file and it worked

(global as {window: unknown}).window = global;
yurakis
  • 331
  • 3
  • 7
  • This won't work if the problem is that the library/code that access window it's accessing a property. Still fails for `window.getComputedStyle()` – perepm Jan 05 '22 at 12:55
1

Try using window object in this way

in .ts file import it

import { WINDOW } from '@ng-toolkit/universal';

then in constructor inject it

constructor(@Inject(WINDOW) public window: Window) {

}

and use it inside any function like below

getBlogs() {
    this.blogsService.getBlogs().subscribe((res) => {
      if (res.message === 'success') {
        this.blogs = res.data.blogs;
        this.window.scroll(0, 0);
      } else {
        console.log('No blogs');
      }
    }, (err) => {
      console.log(err);
    });
  }
Nirali
  • 454
  • 1
  • 6
  • 16
  • 6
    I dont want to directly use Window Object, its needed inside third party lib(intl-tel-input-ng). – Franky Feb 12 '20 at 14:39
  • I know its quite late but for others. For window in third party packages, you can add a piece of code in your server.ts which i have given above. – Abhishek Tripathi Sep 03 '20 at 11:34
0

I have 2 Angular SSR projects which the same config, but one of them faced an issue because have node_modules use window but not validate.

The solution:

  • Find in the main.js which lib make an error, after that search how to pass it.

  • For me, I just upgrade the Nodejs version from 10.x to 14.x the problem was resolve.

Tan Nguyen
  • 947
  • 7
  • 8