Skip to content

Commit ee3972c

Browse files
committed
feat(angular-ssr): support server:start serving of angular routes
1 parent cb0102b commit ee3972c

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

packages/angular-ssr/README.md

+19-16
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
## Configure Deepkit App
44

5-
- Make sure to put your main application inside `app.ts` and export the `App` instance:
5+
- Make sure to put your main application inside `app.ts` and configure it in your `angular.json`:
66

77
In `src/server/app.ts`:
88

99
```typescript
1010
import { App } from '@deepkit/app';
1111
import { FrameworkModule } from '@deepkit/framework';
12-
import { AngularModule } from '@deepkit/angular-ssr';
12+
import { AngularModule, RequestHandler } from '@deepkit/angular-ssr';
1313

14-
export const app = new App({
14+
const app = new App({
1515
controllers: [
1616
// your controllers
1717
],
@@ -20,12 +20,23 @@ export const app = new App({
2020
],
2121
imports: [
2222
new FrameworkModule({}),
23-
new AngularModule()
23+
new AngularModule({
24+
moduleUrl: import.meta.url,
25+
})
2426
]
2527
});
26-
```
2728

28-
Create a `src/server/server.ts` and configure it in your `angular.json`:
29+
const main = isMainModule(import.meta.url);
30+
31+
if (main) {
32+
void app.run(); //allows to call all CLI commands, including server:start
33+
}
34+
35+
export const reqHandler = main
36+
//when in main, we don't want to create a new request handler
37+
? () => undefined
38+
: app.get(RequestHandler).create();
39+
```
2940

3041
```json
3142
{
@@ -36,22 +47,14 @@ Create a `src/server/server.ts` and configure it in your `angular.json`:
3647
"server": "src/main.server.ts",
3748
"outputMode": "server",
3849
"ssr": {
39-
"entry": "src/server/server.ts"
50+
"entry": "src/server/app.ts"
4051
},
4152
"browser": "src/main.ts"
4253
}
4354
}
4455
```
4556

46-
In `src/server/server.ts`:
47-
48-
```typescript
49-
import { app } from './app';
50-
import { RequestHandler } from '@deepkit/angular-ssr';
51-
import { AngularNodeAppEngine } from '@angular/ssr/node';
52-
53-
export const reqHandler = app.get(RequestHandler).create(import.meta.url, new AngularNodeAppEngine());
54-
````
57+
Make sure to have `src/server/app.ts` also in your tsconfig.
5558

5659
## Configure Angular App
5760

packages/angular-ssr/src/angular.ts

+23-10
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class AngularConfig {
4747
* @see REQUEST_CONTEXT
4848
*/
4949
serverBaseUrl: string = '';
50+
51+
/**
52+
* Value of `import.meta.url` in the main entry point module (usually app.ts/server.ts).
53+
*/
54+
moduleUrl: string = '';
5055
}
5156

5257
/**
@@ -62,26 +67,27 @@ class AngularRequestContext {
6267
}
6368
}
6469

65-
let _ngApp: AngularNodeAppEngine | undefined = undefined;
70+
class AngularState {
71+
ngApp: AngularNodeAppEngine = new AngularNodeAppEngine()
72+
}
6673

6774
class AngularListener {
6875
constructor(
6976
public requestContext: AngularRequestContext,
77+
public state: AngularState,
7078
) {
7179
}
7280

7381
@eventDispatcher.listen(httpWorkflow.onRoute, 102) //102 after 101=static listener, 100=default listener
7482
async onRoute(event: typeof httpWorkflow.onRoute.event) {
7583
if (event.route) return; //already found
76-
if (!_ngApp) return;
7784

78-
const promise = _ngApp.handle(event.request, this.requestContext);
85+
const promise = this.state.ngApp.handle(event.request, this.requestContext);
7986
if (!promise) return;
8087

8188
event.routeFound(new RouteConfig('angular', ['GET'], event.request.url || '', {
8289
type: 'function',
8390
fn: async (req: HttpRequest, res: HttpResponse) => {
84-
if (!_ngApp) return;
8591
const response = await promise;
8692
if (!response) {
8793
throw new HttpNotFoundError();
@@ -99,6 +105,12 @@ class AngularStaticListener {
99105
public localPath: string = '';
100106
public path: string = '/'; //public path
101107

108+
constructor(
109+
protected config: AngularConfig,
110+
) {
111+
this.localPath = resolve(dirname(fileURLToPath(this.config.moduleUrl)), '../browser');
112+
}
113+
102114
@eventDispatcher.listen(httpWorkflow.onRoute, 101) //after default route listener at 100
103115
onRoute(event: typeof httpWorkflow.onRoute.event) {
104116
if (event.sent) return;
@@ -123,6 +135,7 @@ export class RequestHandler {
123135
protected started: boolean = false;
124136

125137
constructor(
138+
protected config: AngularConfig,
126139
protected logger: Logger,
127140
protected requestContext: AngularRequestContext,
128141
protected http: HttpKernel,
@@ -131,19 +144,17 @@ export class RequestHandler {
131144
) {
132145
}
133146

134-
create(url: string, ngApp: AngularNodeAppEngine): NodeRequestHandlerFunction {
135-
this.staticListener.localPath = resolve(dirname(fileURLToPath(url)), '../browser');
136-
147+
create(): NodeRequestHandlerFunction {
137148
const global = ((globalThis as any).deepkitAngular ||= {}) as {
138149
server?: ApplicationServer,
139150
started?: boolean,
140151
};
141152

142153
const waitForClose = global.server ? global.server.close() : Promise.resolve();
143-
_ngApp = ngApp;
154+
const mainModule = isMainModule(this.config.moduleUrl);
144155

145156
// We only listen for process signals in the main module.
146-
const listenOnSignals = isMainModule(url);
157+
const listenOnSignals = mainModule;
147158
global.server = this.server;
148159

149160
const waitBootstrap = waitForClose.then(() => this.server.start({
@@ -157,7 +168,7 @@ export class RequestHandler {
157168
this.requestContext.serverBaseUrl = `http://${host}`;
158169

159170
if (!this.requestContext.serverBaseUrl) {
160-
if (isMainModule(url)) {
171+
if (mainModule) {
161172
this.requestContext.serverBaseUrl = 'http://localhost:8080';
162173
} else {
163174
//angular dev server
@@ -200,11 +211,13 @@ export class AngularModule extends createModuleClass({
200211
RequestHandler,
201212
AngularRequestContext,
202213
AngularStaticListener,
214+
AngularState,
203215
],
204216
exports: [
205217
RequestHandler,
206218
AngularRequestContext,
207219
AngularStaticListener,
220+
AngularState,
208221
],
209222
listeners: [
210223
AngularListener,

0 commit comments

Comments
 (0)