I have an Angular 16 app, using Angular Fire, firebaseui and I have recently installed Angular Universal.
Whenever I run npm run dev:ssr to enable SSR I receive this error -
./node_modules/dialog-polyfill/dialog-polyfill.js:4
var supportCustomEvent = window.CustomEvent;
^
ReferenceError: window is not defined
at <anonymous> (./node_modules/dialog-polyfill/dialog-polyfill.js:4:28)
at Object.44252 (./node_modules/dialog-polyfill/dialog-polyfill.js:738:2)
at __webpack_require__ (./webpack/bootstrap:19:1)
at Module.73697 (./node_modules/express/node_modules/serve-static/index.js:210:1)
at __webpack_require__ (./webpack/bootstrap:19:1)
at Module.10388 (./src/app/components/home/home.component.html:46:10)
at __webpack_require__ (./webpack/bootstrap:19:1)
at Module.11838 (./server.ts:74:35)
at __webpack_require__ (./webpack/bootstrap:19:1)
at Module.50041 (./src/app/app.component.html:3:8)
Node.js v20.9.0
A server error has occurred.
node exited with 1 code.
The dialog-polyfill package is brought in as a dependency for firebaseui. It is not used anywhere else.
I have tried to mitigate against this issue using platformBrowser and also the domino package but am still facing the same error. Any ideas?
login.component.ts
isBrowser: boolean = false;
constructor(
@Inject(PLATFORM_ID) private platformId: Object
) {
this.isBrowser = isPlatformBrowser(platformId);
}
ngOnInit(): void {
if (isPlatformBrowser(this.platformId)) {
if (!this.ui) {
this.ui = new firebaseui.auth.AuthUI(this.auth as any);
}
const uiConfig: firebaseui.auth.Config = {
signInOptions: [
EmailAuthProvider.PROVIDER_ID,
],
signInSuccessUrl: '/',
credentialHelper: firebaseui.auth.CredentialHelper.NONE,
tosUrl: '/privacy-policy',
privacyPolicyUrl: '/privacy-policy',
callbacks: {
signInSuccessWithAuthResult: (authResult: { user: User | null; }, redirectUrl: any) => {
this.onLoginSuccessful(authResult.user);
return false;
},
uiShown: () => {
const loader = document.getElementById('loader');
if (loader) {
loader.style.display = 'none';
}
},
signInFailure: (error: any) => {
console.error(error);
alert('Sign-in failed. Please try again with correct username & password.');
return Promise.resolve();
}
},
signInFlow: 'popup',
autoUpgradeAnonymousUsers: true,
siteName: 'My App'
};
this.ui.start('#firebaseui-auth-container', uiConfig);
this.auth.onAuthStateChanged((user: any) => {
if (!user && this.ui.isPendingRedirect()) {
this.ui.start('#firebaseui-auth-container', uiConfig);
}
});
}
}
login.component.html
<div *ngIf="isBrowser" id="firebaseui-auth-container" class="auth-container">
server.ts
// domino to create dom in server
const domino = require('domino');
const fs = require('fs');
const path = require('path');
// Use the browser index.html as template for the mock window
const template = fs
.readFileSync(path.join(join(process.cwd(), 'dist/<PROJECTNAME>/browser'), 'index.html'))
.toString();
// Shim for the global window and document objects.
const window = domino.createWindow(template);
global['window'] = window;
global['document'] = window.document;
package.json
"@angular/fire": "~7.6.1",
"@nguniversal/express-engine": "^16.2.0",
"domino": "^2.1.6",
"firebase": "^9.23.0",
"firebaseui": "^6.1.0",
I have rebuilt the server.ts file using npm run build:ssr after making and saving the changes.
I haven't seen it explicitly stated but what I've senn implicity implied stated, by other libraries and the Firebaseui GitHub repo is that Firebaseui does not work with SSR. I would suggest using another library that is compatible with your Angular app or writing the interface and TS code yourself, although make sure you monitor for security concerns.