In my Angular v18 project with SSR enabled, I am trying to get hold of a cookie inside the APP_INITIALIZER function. I'm using ngx-cookie-service and set it up with their instructions for SSR.
The app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({eventCoalescing: true}),
provideRouter(routes),
provideClientHydration(),
provideHttpClient(withFetch()),
{
provide: APP_INITIALIZER,
useFactory: () => {
const cookieService = inject(SsrCookieService);
const authService = inject(AuthService);
return () => new Promise((resolve, reject) => {
const isAuthenticated = cookieService.check("idToken");
console.log(isAuthenticated);
if (isAuthenticated) {
const idToken = cookieService.get("idToken");
authService.setUserCredentials(idToken);
console.log(authService.getIsAuthenticated());
}
resolve(true);
});
},
multi: true,
}
]
};
In nav-bar.component.ts
private authService = inject(AuthService);
isAuthenticated = this.authService.getIsAuthenticated();
And in the nav-bar.component.ts template
@if (!isAuthenticated) {
<button routerLink="login">Login</button>
} @else {
<button routerLink="profile">My Account</button>
}
The result is that in the IDE terminal, the console log in app.config.ts
is false
, then in the browser console it's true
. This causes the first render of the navigation bar to show Login
and then immediately re-render and show My Account
.
The <app-nav>
is in the AppComponent
<app-nav/>
<router-outlet/>
<app-footer/>
I've tried injecting the DOCUMENT
and calling document.cookie
, but the page loads with the NotYetImplemented
error.
I've also tried with a BaseComponent
on /
route and a Resolve
on it and passing a boolean
as a required input to <app-nav/>
, but the effect is the same: Login
on first render and My Account
on second.
I am a bit confused as to what's happening and not sure what knowledge I am missing to be able to achieve the value public isAuthenticated: boolean = false;
in AuthService
to be true
before the app's first render.
Any help is appreciated, thank you!
EDIT: Stackblitz
Steps to reproduce:
Inicia Sesión
buttonContinuar
button to set up a cookie with idToken
nameInicia Sesión
button first and then a re-render changing to Mi cuenta
buttonThe cookie service does not work when you do npm run start
(ng serve
), but it works great when you run the SSR server.
So you can ignore these bugs and carry on development, because when you deploy with SSR, it should work fine.
Run npm run build
first.
Then run npm run serve:ssr:PizzeriaAngularFE
open the application and you should see the service showing that the application is authenticated, after the first login.
I made a small correction to you code, looking at the latest documentation on their github page. It might also be not needed and you can use the original method on their ngx-cookie-service - npm page
import { REQUEST as SSR_REQUEST } from "ngx-cookie-service-ssr";
...
...
server.get('*', (req, res, next) => {
const {protocol, originalUrl, baseUrl, headers} = req;
commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [
{provide: APP_BASE_HREF, useValue: baseUrl},
{provide: SSR_REQUEST, useValue: req}, // <- changed here!
{provide: 'RESPONSE', useValue: res},
],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});