Skip to content

@firebase/analytics: "ReferenceError: window is not defined" with SSR (Angular Universal) #2283

@blove

Description

@blove

Version info

Angular CLI: 8.3.21
Node: 10.15.0
OS: darwin x64
Angular: 8.2.14
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router, service-worker

Package Version

@angular-devkit/architect 0.803.21
@angular-devkit/build-angular 0.803.21
@angular-devkit/build-optimizer 0.803.21
@angular-devkit/build-webpack 0.803.21
@angular-devkit/core 8.3.21
@angular-devkit/schematics 8.3.21
@angular/cdk 8.2.3
@angular/cli 8.3.21
@angular/fire 5.3.0
@angular/material 8.2.3
@angular/pwa 0.803.21
@ngtools/webpack 8.3.21
@nguniversal/express-engine 8.2.6
@nguniversal/module-map-ngfactory-loader 8.2.6
@schematics/angular 8.3.21
@schematics/update 0.803.21
rxjs 6.5.4
typescript 3.5.3
webpack 4.39.2

How to reproduce these conditions

This is an issue that seems to only occur with SSR (Angular Universal).
As such, the steps to reproduce involve cloning a sample repository, installing dependencies, building, and then running the node server locally.

Steps to set up and reproduce

  1. Clone the repository located at: https://github.com/blove/angularfire-prerender-analytics
  2. Run the npm run build command to build the Angular project, server project and webpack.
  3. Run the npm run serve:ssr command to start the node server.
  4. Open http://localhost:4000 in your browser (or make the request via curl)

Sample data and security rules

N/A

Debug output

Unhandled Promise rejection: window is not defined ; Zone: <root> ; Task: Promise.then ; Value: ReferenceError: window is not defined
    at findGtagScriptOnPage (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:348:22)
    at factory (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:473:14)
    at Component.instance.INTERNAL.registerComponent.component.Component.setServiceProps.settings [as instanceFactory] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:535:16)
    at Provider.getOrInitializeService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:219:39)
    at Provider.getImmediate (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:120:33)
    at FirebaseAppImpl._getService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:227:49)
    at FirebaseAppImpl.firebaseAppImpl.(anonymous function) [as analytics] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:437:39)
    at MapSubscriber.eval [as project] (webpack://app/./node_modules/@angular/fire/analytics/analytics.js?:129:626)
    at MapSubscriber._next (webpack://app/./node_modules/rxjs/_esm5/internal/operators/map.js?:40:35)
    at MapSubscriber.Subscriber.next (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:63:18) ReferenceError: window is not defined
    at findGtagScriptOnPage (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:348:22)
    at factory (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:473:14)
    at Component.instance.INTERNAL.registerComponent.component.Component.setServiceProps.settings [as instanceFactory] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:535:16)
    at Provider.getOrInitializeService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:219:39)
    at Provider.getImmediate (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:120:33)
    at FirebaseAppImpl._getService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:227:49)
    at FirebaseAppImpl.firebaseAppImpl.(anonymous function) [as analytics] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:437:39)
    at MapSubscriber.eval [as project] (webpack://app/./node_modules/@angular/fire/analytics/analytics.js?:129:626)
    at MapSubscriber._next (webpack://app/./node_modules/rxjs/_esm5/internal/operators/map.js?:40:35)
    at MapSubscriber.Subscriber.next (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:63:18)
Unhandled Promise rejection: window is not defined ; Zone: <root> ; Task: Promise.then ; Value: ReferenceError: window is not defined
    at findGtagScriptOnPage (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:348:22)
    at factory (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:473:14)
    at Component.instance.INTERNAL.registerComponent.component.Component.setServiceProps.settings [as instanceFactory] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:535:16)
    at Provider.getOrInitializeService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:219:39)
    at Provider.getImmediate (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:120:33)
    at FirebaseAppImpl._getService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:227:49)
    at FirebaseAppImpl.firebaseAppImpl.(anonymous function) [as analytics] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:437:39)
    at MapSubscriber.eval [as project] (webpack://app/./node_modules/@angular/fire/analytics/analytics.js?:129:626)
    at MapSubscriber._next (webpack://app/./node_modules/rxjs/_esm5/internal/operators/map.js?:40:35)
    at MapSubscriber.Subscriber.next (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:63:18) ReferenceError: window is not defined
    at findGtagScriptOnPage (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:348:22)
    at factory (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:473:14)
    at Component.instance.INTERNAL.registerComponent.component.Component.setServiceProps.settings [as instanceFactory] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/analytics/dist/index.cjs.js:535:16)
    at Provider.getOrInitializeService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:219:39)
    at Provider.getImmediate (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/component/dist/index.cjs.js:120:33)
    at FirebaseAppImpl._getService (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:227:49)
    at FirebaseAppImpl.firebaseAppImpl.(anonymous function) [as analytics] (/Users/blove/Desktop/angularfire-prerender-analytics/node_modules/@firebase/app/dist/index.node.cjs.js:437:39)
    at MapSubscriber.eval [as project] (webpack://app/./node_modules/@angular/fire/analytics/analytics.js?:129:626)
    at MapSubscriber._next (webpack://app/./node_modules/rxjs/_esm5/internal/operators/map.js?:40:35)
    at MapSubscriber.Subscriber.next (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:63:18)
ERROR { Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'index.js.map'
Error: Cannot match any routes. URL Segment: 'index.js.map'
    at ApplyRedirects.noMatchError (webpack://app/./node_modules/@angular/router/fesm5/router.js?:2531:16)
    at CatchSubscriber.eval [as selector] (webpack://app/./node_modules/@angular/router/fesm5/router.js?:2512:29)
    at CatchSubscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/operators/catchError.js?:40:31)
    at MapSubscriber.Subscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:89:26)
    at MapSubscriber.Subscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:69:18)
    at MapSubscriber.Subscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:89:26)
    at MapSubscriber.Subscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:69:18)
    at MapSubscriber.Subscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:89:26)
    at MapSubscriber.Subscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:69:18)
    at TapSubscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/operators/tap.js?:67:26)
    at resolvePromise (webpack://app/./node_modules/zone.js/dist/zone-node.js?:851:31)
    at resolvePromise (webpack://app/./node_modules/zone.js/dist/zone-node.js?:808:17)
    at eval (webpack://app/./node_modules/zone.js/dist/zone-node.js?:912:17)
    at ZoneDelegate.invokeTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:422:31)
    at Object.onInvokeTask (webpack://app/./node_modules/@angular/core/fesm5/core.js?:26677:33)
    at ZoneDelegate.invokeTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:421:60)
    at Zone.runTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:194:47)
    at drainMicroTaskQueue (webpack://app/./node_modules/zone.js/dist/zone-node.js?:600:35)
    at ZoneTask.invokeTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:501:21)
    at ZoneTask.invoke (webpack://app/./node_modules/zone.js/dist/zone-node.js?:486:48)

Expected behavior

The AngularFireAnalyticsModule uses the @firebase/analytics module that determines if the gtag script is already present in the DOM. This functionality relies on a global window object in the findGtagScriptOnPage() function. This function should check if the window object is first available.

Actual behavior

Using SSR locally, pre-rendering locally, and running the server in a Firebase cloud function all result in this error.

Possible Workaround

One potential workaround I attempted was to mock the window object using domino:

const win = createWindow(template);
(global as any)['window'] = win;
(global as any)['document'] = win.document;

However, this results in another error:

Unhandled Promise rejection: IDB requires a browser environment ; Zone: <root> ; Task: Promise.then ; Value: IDB requires a browser environment undefined
ERROR { Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'index.js.map'
Error: Cannot match any routes. URL Segment: 'index.js.map'
    at ApplyRedirects.noMatchError (webpack://app/./node_modules/@angular/router/fesm5/router.js?:2531:16)
    at CatchSubscriber.eval [as selector] (webpack://app/./node_modules/@angular/router/fesm5/router.js?:2512:29)
    at CatchSubscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/operators/catchError.js?:40:31)
    at MapSubscriber.Subscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:89:26)
    at MapSubscriber.Subscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:69:18)
    at MapSubscriber.Subscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:89:26)
    at MapSubscriber.Subscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:69:18)
    at MapSubscriber.Subscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:89:26)
    at MapSubscriber.Subscriber.error (webpack://app/./node_modules/rxjs/_esm5/internal/Subscriber.js?:69:18)
    at TapSubscriber._error (webpack://app/./node_modules/rxjs/_esm5/internal/operators/tap.js?:67:26)
    at resolvePromise (webpack://app/./node_modules/zone.js/dist/zone-node.js?:851:31)
    at resolvePromise (webpack://app/./node_modules/zone.js/dist/zone-node.js?:808:17)
    at eval (webpack://app/./node_modules/zone.js/dist/zone-node.js?:912:17)
    at ZoneDelegate.invokeTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:422:31)
    at Object.onInvokeTask (webpack://app/./node_modules/@angular/core/fesm5/core.js?:26677:33)
    at ZoneDelegate.invokeTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:421:60)
    at Zone.runTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:194:47)
    at drainMicroTaskQueue (webpack://app/./node_modules/zone.js/dist/zone-node.js?:600:35)
    at ZoneTask.invokeTask (webpack://app/./node_modules/zone.js/dist/zone-node.js?:501:21)
    at ZoneTask.invoke (webpack://app/./node_modules/zone.js/dist/zone-node.js?:486:48)

I pushed an additional branch with this attempted workaround: https://github.com/blove/angularfire-prerender-analytics/tree/domino-fix

This appears to be related to the following issue: firebase/firebase-js-sdk#2336

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions