8

i have created project with firebase store. Now i want to implement server side rendering on it. After i did everything for ssr when i run program this is what i get

ReferenceError: window is not defined
    at Object.ex9U (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:166129:4)
    at __webpack_require__ (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:26:30)
    at Module.vvyD (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:271824:80)
    at __webpack_require__ (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:26:30)
    at Module.PCNd (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:131612:74)
    at __webpack_require__ (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:26:30)
    at Module.ZAI4 (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:154371:80)
    at __webpack_require__ (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:26:30)
    at Module.24aS (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:47619:69)
    at __webpack_require__ (C:\Users\waqas\Desktop\ng-blog\dist\ng-blog\server\main.js:26:30)

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

here are my files package.json

{
    "name": "ng-blog",
    "version": "0.0.0",
    "scripts": {
        "ng": "ng",
        "start": "ng serve",
        "build": "ng build",
        "dev:ssr": "ng run ng-blog:serve-ssr",
        "serve:ssr": "node dist/ng-blog/server/main.js",
        "build:ssr": "ng build --prod && ng run ng-blog:server:production",
        "prerender": "ng run ng-blog:prerender"
    },
    "private": true,
    "dependencies": {
        "@angular/animations": "~11.2.10",
        "@angular/cdk": "^11.2.9",
        "@angular/common": "~11.2.10",
        "@angular/compiler": "~11.2.10",
        "@angular/core": "~11.2.10",
        "@angular/fire": "^6.1.4",
        "@angular/forms": "~11.2.10",
        "@angular/material": "^11.2.9",
        "@angular/platform-browser": "~11.2.10",
        "@angular/platform-browser-dynamic": "~11.2.10",
        "@angular/platform-server": "~11.2.10",
        "@angular/router": "~11.2.10",
        "@nguniversal/express-engine": "^11.2.1",
        "@ntegral/ngx-universal-window": "^1.0.2",
        "@tinymce/tinymce-angular": "^4.2.2",
        "angular-froala-wysiwyg": "^3.2.6-1",
        "angularfire2": "^5.4.2",
        "express": "^4.15.2",
        "firebase": "^7.24.0",
        "rxjs": "~6.6.0",
        "rxjs-compat": "^6.6.7",
        "tinymce": "^5.7.1",
        "tslib": "^2.0.0",
        "zone.js": "~0.11.3"
    },
    "devDependencies": {
        "@angular-devkit/build-angular": "~0.1102.9",
        "@angular/cli": "~11.2.9",
        "@angular/compiler-cli": "~11.2.10",
        "@nguniversal/builders": "^11.2.1",
        "@types/express": "^4.17.0",
        "@types/node": "^12.11.1",
        "typescript": "~4.1.5"
    }
}

Server.ts

import 'zone.js/dist/zone-node';

import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';

import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/ng-blog/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  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 {
  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}`);
  });
}

// 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';

angular.json

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
        "ng-blog": {
            "projectType": "application",
            "schematics": {
                "@schematics/angular:component": {
                    "inlineTemplate": false,
                    "inlineStyle": false,
                    "style": "scss",
                    "skipTests": true
                },
                "@schematics/angular:class": {
                    "skipTests": true
                },
                "@schematics/angular:directive": {
                    "skipTests": true
                },
                "@schematics/angular:guard": {
                    "skipTests": true
                },
                "@schematics/angular:interceptor": {
                    "skipTests": true
                },
                "@schematics/angular:module": {
                    "skipTests": true
                },
                "@schematics/angular:pipe": {
                    "skipTests": true
                },
                "@schematics/angular:service": {
                    "skipTests": true
                }
            },
            "root": "",
            "sourceRoot": "src",
            "prefix": "app",
            "architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser",
                    "options": {
                        "outputPath": "dist/ng-blog/browser",
                        "index": "src/index.html",
                        "main": "src/main.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "tsconfig.app.json",
                        "aot": true,
                        "assets": [
                            "src/favicon.ico",
                            "src/assets"
                        ],
                        "styles": [
                            "src/styles.scss",
                            "src/theme.scss",
                            "node_modules/tinymce/skins/ui/oxide/skin.min.css",
                            "node_modules/tinymce/skins/ui/oxide/content.min.css",
                            "node_modules/tinymce/skins/content/default/content.min.css",
                            "./node_modules/froala-editor/css/froala_editor.pkgd.min.css",
                            "./node_modules/froala-editor/css/froala_style.min.css"

                        ],
                        "scripts": [
                            "node_modules/tinymce/tinymce.min.js",
                            "node_modules/tinymce/themes/silver/theme.js"
                        ]
                    },
                    "configurations": {
                        "production": {
                            "fileReplacements": [{
                                "replace": "src/environments/environment.ts",
                                "with": "src/environments/environment.prod.ts"
                            }],
                            "optimization": true,
                            "outputHashing": "all",
                            "sourceMap": false,
                            "namedChunks": false,
                            "extractLicenses": true,
                            "vendorChunk": false,
                            "buildOptimizer": true,
                            "budgets": [{
                                    "type": "initial",
                                    "maximumWarning": "2mb",
                                    "maximumError": "5mb"
                                },
                                {
                                    "type": "anyComponentStyle",
                                    "maximumWarning": "6kb",
                                    "maximumError": "10kb"
                                }
                            ]
                        }
                    }
                },
                "serve": {
                    "builder": "@angular-devkit/build-angular:dev-server",
                    "options": {
                        "browserTarget": "ng-blog:build"
                    },
                    "configurations": {
                        "production": {
                            "browserTarget": "ng-blog:build:production"
                        }
                    }
                },
                "extract-i18n": {
                    "builder": "@angular-devkit/build-angular:extract-i18n",
                    "options": {
                        "browserTarget": "ng-blog:build"
                    }
                },
                "server": {
                    "builder": "@angular-devkit/build-angular:server",
                    "options": {
                        "outputPath": "dist/ng-blog/server",
                        "main": "server.ts",
                        "tsConfig": "tsconfig.server.json"
                    },
                    "configurations": {
                        "production": {
                            "outputHashing": "media",
                            "fileReplacements": [
                                {
                                    "replace": "src/environments/environment.ts",
                                    "with": "src/environments/environment.prod.ts"
                                }
                            ],
                            "sourceMap": false,
                            "optimization": true
                        }
                    }
                },
                "serve-ssr": {
                    "builder": "@nguniversal/builders:ssr-dev-server",
                    "options": {
                        "serverTarget": "ng-blog:server",
                        "browserTarget": "ng-blog:build"
                        
                    },
                    "configurations": {
                        "production": {
                            "browserTarget": "ng-blog:build:production",
                            "serverTarget": "ng-blog:server:production"
                        }
                    }
                },
                "prerender": {
                    "builder": "@nguniversal/builders:prerender",
                    "options": {
                        "browserTarget": "ng-blog:build:production",
                        "serverTarget": "ng-blog:server:production",
                        "routes": [
                            "/"
                        ]
                    },
                    "configurations": {
                        "production": {}
                    }
                }
            }
        }
    },
    "defaultProject": "ng-blog"
}

i dont understand what is the issue when i use npm run dev:ssr i get this error

2
  • on SSR, there is no window, because you are on the server, not on the browser. So you have to make your window null-safe. You may see many trick on google about that. Commented Apr 27, 2021 at 12:32
  • Have a look here stackoverflow.com/a/56936770/1160794 Commented May 4, 2021 at 9:15

4 Answers 4

7

I faced a similar issue, and in my scenario, the problem stemmed from the Leaflet map library. To address this, I implemented a solution by conditionally loading the Leaflet library only when running in a browser environment. This resolved the problem for me.

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

export class MapComponent implements OnInit {

private map!: L.Map;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {}

private centroid: L.LatLngExpression = [16.81897, 10.16579]; //
 ngOnInit(): void {
    if (isPlatformBrowser(this.platformId)) {
      
      import('leaflet').then((L) => {
        this.initMap(L);
      });
    }
  }

private initMap(L: any): void {
this.map = L.map('map', {
  center: this.centroid,
  zoom: 6,
       });
}
}
Sign up to request clarification or add additional context in comments.

Comments

4

Add "module": "commonjs", inside compilerOptions at tsconfig.server.json.

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

credit link

1 Comment

this doesn't work with angular 17
2

Install the ssr-window from NPM (https://www.npmjs.com/package/ssr-window)

In JS File use like below -

import {getWindow} from "ssr-window";

ngOnInit() {
const width = getWindow().innerWidth;
}

There is no change for the Html file, you can use like below-

<main  (window:resize)="onResize()">
  <app-header></app-header>
</main>

Comments

2

if (isPlatformBrowser(this.platformId)) {

//your localstorage or all your windows related code, inset inside this

}

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.