i have created a Angular app with @angular/ssr in v-17. It works fine in localhost but when deployed to production it is not rendering from server. I mean its rendering in network tab but is not showing ng-server-context=”ssr” in the app-root of production build.
so what we are doing is we are employing a jenkins server to build the ssr files then copy the browser folder contents to /var/www/html then in the jenkins workspace itself we run the server’s main.js using sudo pm2 start main.js –name “frontend-server” –env production . And it gets started when checked in pm2 logs. and after the jenkins build is successful we are able to see the server passing doc in network tab but when checked in page source there is no ng-server-context=”ssr” in the app-root of production build. And we havent configured a proxy for server side rendering in apache2. please help me out with good solutions im a total noob in angular/ssr
my server.ts
import 'zone.js/node';
import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import AppServerModule from './src/main.server';
//The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), '/dist/kaamresume/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html'))
? join(distFolder, 'index.original.html')
: join(distFolder, 'index.html');
const commonEngine = new CommonEngine();
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 Angular engine
server.get('*', (req:any, res:any, next:any) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap: AppServerModule,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: distFolder,
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});
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}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export default AppServerModule;
my server.main.ts:
export { AppServerModule as default } from './app/app.module.server';
my app.module.server.ts:
import { NgModule } from '@angular/core';
import { provideServerRendering, ServerModule } from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
@NgModule({
imports: [
AppModule,
ServerModule,
],
bootstrap: [AppComponent],
providers:[provideServerRendering()]
})
export class AppServerModule {}
My app.module.ts:
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
ContainerModule,
BrowserAnimationsModule,
MaterialModule,
MatInputModule,
QuillModule.forRoot(),
NgbModule,
MatProgressSpinnerModule,
HttpClientModule,
NgxStripeModule.forRoot('pk_test_51OODACSIlX5eKJquLWNoSPyZvKHBwoL6J5Cg4v7w6bNCBWofCiAZeFOHIWpqsnHPnRrkKWzZbNEQjiUH3h1Mg10000KYFkmFhP'),
MatSnackBarModule
],
providers: [
{
provide: HTTP_INTERCEPTORS,
// useClass: InterceptorService,
useClass: InterceptorService,
multi: true
},
{
provide: RouteReuseStrategy,
useClass: RouteReuseService
},
DatePipe,
provideClientHydration(),
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent]
})
export class AppModule { }
my main.ts:
/// <reference types="@angular/localize" />
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import 'zone.js';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
if (environment.production) {
enableProdMode();
}
my tsconfig.server.json:
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "./out-tsc/server",
"types": [
"node",
"@angular/localize"
]
},
"files": [
"src/main.server.ts",
"server.ts"
]
}
my tsconfig.app.json
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": [
"@angular/localize",
"jquery"
]
},
"files": [
"src/main.ts",
// "src/polyfills.ts"
],
"include": [
"src/**/*.d.ts",
// "src/**/*.ts"
],
"exclude": [
"src/**/*.spec.ts"
]
}