0

In Angular 7 Universal, I was able to add 3rd party scripts using postscribe (without any special settings).

Now I am trying to use postscribe in Angular 9 Universal project like

if(this.isBrowser) {
    // ... my postscribe code here
}

but its giving below error

var work = window.document.createElement('div');
                           ^

ReferenceError: window is not defined
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204958:14)
    at __webpack_require__ (E:\Projects\angular-universal-starter\dist-server\main.js:204658:31)
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204703:19)
    at __webpack_require__ (E:\Projects\angular-universal-starter\dist-server\main.js:204658:31)
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204687:21)
    at __webpack_require__ (E:\Projects\angular-universal-starter\dist-server\main.js:204658:31)
    at E:\Projects\angular-universal-starter\dist-server\main.js:204678:19
    at E:\Projects\angular-universal-starter\dist-server\main.js:204681:11
    at webpackUniversalModuleDefinition (E:\Projects\angular-universal-starter\dist-server\main.js:204636:21)
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204638:4)

A server error has occurred.
node exited with 1 code.

In server.ts I have added

// for mock global window by domino
const win = domino.createWindow(template);
// mock
global['window'] = win;

Not sure why its giving this error, any clue?

I am using "postscribe": "^2.0.8".

And I have built my app on top of the starter project

Complete Log

$ npm run ssr

> universal-demo@7.0.0 ssr E:\Projects\angular-universal-starter
> ng run universal-demo:serve-ssr

****************************************************************************************
This is a simple server for use in testing or debugging Angular applications locally.
It hasn't been reviewed for security issues.

DON'T USE IT FOR PRODUCTION!
****************************************************************************************
Hash: 8e8bf0402197478a1be2
Time: 43386ms
Built at: 07/01/2020 8:30:09 PM
      Asset      Size  Chunks                          Chunk Names
    main.js  10.7 MiB    main  [emitted]        [big]  main
main.js.map  11.2 MiB    main  [emitted] [dev]         main
Entrypoint main [big] = main.js main.js.map
chunk {main} main.js, main.js.map (main) 10.3 MiB [entry] [rendered]

chunk {app-static-static-module} app-static-static-module.js, app-static-static-module.js.map (app-static-static-module) 59.5 kB  [rendered]
chunk {main} main.js, main.js.map (main) 928 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 608 kB [initial] [rendered]
chunk {polyfills-es5} polyfills-es5.js, polyfills-es5.js.map (polyfills-es5) 694 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 9.07 kB [entry] [rendered]
chunk {styles} styles.css, styles.css.map (styles) 205 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 6.41 MB [initial] [rendered]
Date: 2020-07-01T15:30:16.786Z - Hash: 466864382a957d66d22c - Time: 45587ms

Compiled successfully.
E:\Projects\angular-universal-starter\dist-server\main.js:204958
                var work = window.document.createElement('div');
                           ^

ReferenceError: window is not defined
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204958:14)
    at __webpack_require__ (E:\Projects\angular-universal-starter\dist-server\main.js:204658:31)
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204703:19)
    at __webpack_require__ (E:\Projects\angular-universal-starter\dist-server\main.js:204658:31)
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204687:21)
    at __webpack_require__ (E:\Projects\angular-universal-starter\dist-server\main.js:204658:31)
    at E:\Projects\angular-universal-starter\dist-server\main.js:204678:19
    at E:\Projects\angular-universal-starter\dist-server\main.js:204681:11
    at webpackUniversalModuleDefinition (E:\Projects\angular-universal-starter\dist-server\main.js:204636:21)
    at Object.<anonymous> (E:\Projects\angular-universal-starter\dist-server\main.js:204638:4)

A server error has occurred.
node exited with 1 code.
connect ECONNREFUSED 127.0.0.1:55182
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! universal-demo@7.0.0 ssr: `ng run universal-demo:serve-ssr `
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the universal-demo@7.0.0 ssr script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\test\AppData\Roaming\npm-cache\_logs\2020-07-01T15_30_47_590Z-debug.log

Steps to generate the error

  1. Clone angular-universal-starter project
  2. Run npm i postscribe
  3. Run npm install
  4. Load script in app.component.ts as
import { Component, OnInit, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import postscribe from "postscribe";
import { MetaService } from '@ngx-meta/core';

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet><span id="myscript"></span>',
})
export class AppComponent implements OnInit {
  isBrowser: boolean;

  constructor(
    private readonly meta: MetaService,
    @Inject(PLATFORM_ID) platformId: Object
    ) {
      this.isBrowser = isPlatformBrowser(platformId);
    this.meta.setTag('og:title', 'home ctor');
  }

  ngOnInit(): void {
    this._loadScript();
  }

  private _loadScript() {
    if(this.isBrowser) {
      postscribe(
        "#myscript",
        '<script type="text/javascript">alert(\'Postscribe is working.\');</script>',
        {
          done: () => {
            console.log("SSL Certificate Seal loaded");
          }
        }
      );
    }
  }
}
  1. Run npm run ssr.
  2. You will see the error on the command prompt.
Junaid
  • 2,572
  • 6
  • 41
  • 77
  • Did you track down which module that piece of code belongs to? Are you sure it's from postscribe? And do you get the error as soon as you run the SSR server script, or while doing page rendering (i.e. after accessing the page)? – David Jul 01 '20 at 12:16
  • @David 1) I am sure error is due to postscribe, because as soon as I remove postscribe code, everything works fine. 2) I get the error after the code compiled successfully, but during running SSR server script. Also I am adding complete log. – Junaid Jul 01 '20 at 15:34
  • Can you show your entire `server.ts` file? And do a `console.log(global['window'])` after assigning it? – David Jul 02 '20 at 06:53
  • @David I have added "Steps to generate the error" at the end of my question. – Junaid Jul 02 '20 at 07:44
  • 1
    Maybe try adding the script to index.html instead, remove postscribe import and add `declare let postscribe: any;` above your component declaration – David Jul 02 '20 at 09:20

1 Answers1

1

The problem is that postscribe uses prescribe, which tries to access the dom element when the module is imported (so not when you render the page, but when the SSR node process starts)

let work = window.document.createElement('div');

Normally, using domino like you did should remove the error, but it looks like postscribe is imported before server.ts has setup domino

Anyway, since postscribe looks like it's for modifying content after page load, you could try directly importing the script in index.html

 <script src="https://cdnjs.cloudflare.com/ajax/libs/postscribe/2.0.8/postscribe.min.js"></script>

then remove your import for postscribe and just use the global variable from the script

import { Component, OnInit, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
//import postscribe from "postscribe"; <== remove this
import { MetaService } from '@ngx-meta/core';

declare let postscribe: any; //add this
David
  • 33,444
  • 11
  • 80
  • 118