I am looking for a way to provide tokens from the server-side when prerendering the application using the prerender script.
The issue I am facing is linked to this issue
Providing the tokens for the app does not work.
I am giving the values as empty strings as the providers are expecting strings which are: (req.headers['user-agent']
and a string URL of the request
)
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/web/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,
providers: [
{
provide: UNIVERSAL_USER_AGENT,
useValue: '',
},
{
provide: UNIVERSAL_LOCATION,
useValue: '',
},
],
})
);
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 },
provideLocation(req),
provideUserAgent(req),
],
});
});
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}`);
});
}
I have also provided the tokens in the server module but still, it does not pick them up.
@NgModule({
imports: [AppModule, ServerModule, UniversalModule, FlexLayoutServerModule],
bootstrap: [AppComponent],
providers: [
{
provide: UNIVERSAL_USER_AGENT,
useValue: '',
},
{
provide: UNIVERSAL_LOCATION,
useValue: '',
},
],
})
export class AppServerModule {}
Is there a way to achieve this? I am still confused by dependency injection. The normal SSR works because I am able to provide the tokens using factories since they depend on the req object. But with the pretender, I do not have req object so I cannot use the factories. I'd appreciate any suggestions and ideas
I have used Scully, the app pre-renders, my issue is solved.
To get started with Scully, you can check out this link.
How I got it working was to install Scully using the Angular CLI.
The add
schematic will do some changes to your project for basic configuration, I think it adds also the scripts I have noted below.
ng add @scullyio/init
I then added scripts in my package.json
file like below
"scully": "npx scully --",
"scully:serve": "npx scully serve --"
After installing Scully, I just needed to build my app using the Angular build script: ng build
and npm run scully
. This pre-rendered my application without any issues.
There was a limitation I have faced for dynamic routes where I had a Angular route config like /some-path/232
and the 232
is dynamic and unknown at build time, I have circumvented this limitation by changing that route path to /some-path
and using queryParams
to pass the data I needed for the route/component.
I hope that helps.