Skip to content

Commit b370e22

Browse files
authored
Merge pull request #13911 from IgniteUI/angular-ssr
test(ssr): extending the bundle-test project for SSR
2 parents 4663691 + c2b57b3 commit b370e22

File tree

18 files changed

+164
-60
lines changed

18 files changed

+164
-60
lines changed

.github/workflows/nodejs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
node-version: [18.x, 20.5.x]
19+
node-version: [18.x, 20.x]
2020

2121
steps:
2222
- name: Checkout
@@ -56,7 +56,7 @@ jobs:
5656
run: |
5757
npm run build:i18n
5858
npm run test:i18n:dist
59-
- name: Bundle Tree-Shake Test
59+
- name: Bundle Tree-Shake & SSR Test
6060
run: npm run build:bundletest
6161
- name: Publish to coveralls.io
6262
if: github.repository == 'IgniteUI/igniteui-angular' && matrix.node-version == '18.x'

angular.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@
270270
"includePaths": [
271271
"node_modules"
272272
]
273+
},
274+
"server": "projects/bundle-test/src/main.server.ts",
275+
"prerender": true,
276+
"ssr": {
277+
"entry": "projects/bundle-test/server.ts"
273278
}
274279
},
275280
"configurations": {

projects/bundle-test/server.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { APP_BASE_HREF } from '@angular/common';
2+
import { CommonEngine } from '@angular/ssr';
3+
import express from 'express';
4+
import { fileURLToPath } from 'node:url';
5+
import { dirname, join, resolve } from 'node:path';
6+
import bootstrap from './src/main.server';
7+
8+
// The Express app is exported so that it can be used by serverless Functions.
9+
export function app(): express.Express {
10+
const server = express();
11+
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
12+
const browserDistFolder = resolve(serverDistFolder, '../browser');
13+
const indexHtml = join(serverDistFolder, 'index.server.html');
14+
15+
const commonEngine = new CommonEngine();
16+
17+
server.set('view engine', 'html');
18+
server.set('views', browserDistFolder);
19+
20+
// Example Express Rest API endpoints
21+
// server.get('/api/**', (req, res) => { });
22+
// Serve static files from /browser
23+
server.get('*.*', express.static(browserDistFolder, {
24+
maxAge: '1y'
25+
}));
26+
27+
// All regular routes use the Angular engine
28+
server.get('*', (req, res, next) => {
29+
const { protocol, originalUrl, baseUrl, headers } = req;
30+
31+
commonEngine
32+
.render({
33+
bootstrap,
34+
documentFilePath: indexHtml,
35+
url: `${protocol}://${headers.host}${originalUrl}`,
36+
publicPath: browserDistFolder,
37+
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
38+
})
39+
.then((html) => res.send(html))
40+
.catch((err) => next(err));
41+
});
42+
43+
return server;
44+
}
45+
46+
function run(): void {
47+
const port = process.env['PORT'] || 4000;
48+
49+
// Start up the Node server
50+
const server = app();
51+
server.listen(port, () => {
52+
console.log(`Node Express server listening on http://localhost:${port}`);
53+
});
54+
}
55+
56+
run();

projects/bundle-test/src/app/app.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { AppComponent } from './app.component';
33

44
describe('AppComponent', () => {
55
beforeEach(() => TestBed.configureTestingModule({
6-
declarations: [AppComponent]
6+
imports: [AppComponent]
77
}));
88

99
it('should create the app', () => {

projects/bundle-test/src/app/app.component.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { Component } from '@angular/core';
22
import { ChipResourceStringsBG } from 'igniteui-angular-i18n';
3+
import { RouterOutlet } from '@angular/router';
34

45
@Component({
5-
selector: 'app-root',
6-
templateUrl: './app.component.html',
7-
styleUrls: ['./app.component.scss']
6+
selector: 'app-root',
7+
templateUrl: './app.component.html',
8+
styleUrls: ['./app.component.scss'],
9+
standalone: true,
10+
imports: [RouterOutlet]
811
})
912
export class AppComponent {
1013
protected chipStrings = ChipResourceStringsBG;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
2+
import { provideServerRendering } from '@angular/platform-server';
3+
import { appConfig } from './app.config';
4+
5+
const serverConfig: ApplicationConfig = {
6+
providers: [
7+
provideServerRendering()
8+
]
9+
};
10+
11+
export const config = mergeApplicationConfig(appConfig, serverConfig);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { ApplicationConfig } from '@angular/core';
2+
import { provideRouter } from '@angular/router';
3+
4+
import { routes } from './app.routes';
5+
import { provideClientHydration } from '@angular/platform-browser';
6+
7+
export const appConfig: ApplicationConfig = {
8+
providers: [provideRouter(routes), provideClientHydration()]
9+
};

projects/bundle-test/src/app/app.module.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
import { NgModule } from '@angular/core';
2-
import { RouterModule, Routes } from '@angular/router';
1+
import { Routes } from '@angular/router';
32
import { ChipComponent } from './chip/chip.component';
3+
import { ButtonGroupComponent } from './button-group/button-group.component';
44

5-
const routes: Routes = [
5+
export const routes: Routes = [
66
{ path: '', redirectTo: '/chip', pathMatch: 'full' },
77
{ path: 'chip', component: ChipComponent },
8+
{ path: 'button-group', component: ButtonGroupComponent}
89
// { path: 'form', loadComponent: () => import('./form/form.component').then(m => m.FormComponent) },
910
// { path: 'stepper', loadComponent: () => import('./stepper/stepper.component').then(m => m.StepperComponent) },
1011
// { path: 'grid', loadComponent: () => import('./grid/grid.component').then(m => m.GridComponent) }
1112
];
12-
13-
@NgModule({
14-
imports: [RouterModule.forRoot(routes)],
15-
exports: [RouterModule]
16-
})
17-
export class AppRoutingModule { }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<igx-buttongroup>
2+
<button type="button" igxButton="flat">Button 1</button>
3+
<button type="button" igxButton="flat">Button 2</button>
4+
<button type="button" igxButton="flat">Button 3</button>
5+
</igx-buttongroup>

0 commit comments

Comments
 (0)