Skip to content

Commit e04b891

Browse files
committed
refactor(@angular/ssr): remove duplicate code and streamline functionality
This commit cleans up duplicate code left from the previous implementations of process, serve, and render. Additionally, prerender serve now exclusively handles HEAD and GET requests, aligning with updated handling requirements. The private `renderStatic` method has been removed in favor of the `handle` method for improved maintainability. (cherry picked from commit e16cbb9)
1 parent 1e37b59 commit e04b891

File tree

11 files changed

+338
-217
lines changed

11 files changed

+338
-217
lines changed

goldens/public-api/angular/ssr/index.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { EnvironmentProviders } from '@angular/core';
99
// @public
1010
export class AngularAppEngine {
1111
handle(request: Request, requestContext?: unknown): Promise<Response | null>;
12+
static ɵallowStaticRouteRender: boolean;
1213
static ɵhooks: Hooks;
1314
}
1415

packages/angular/build/src/tools/vite/middlewares/ssr-middleware.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ export function createAngularSsrInternalMiddleware(
4444
ɵgetOrCreateAngularServerApp: typeof getOrCreateAngularServerApp;
4545
};
4646

47-
const angularServerApp = ɵgetOrCreateAngularServerApp();
47+
const angularServerApp = ɵgetOrCreateAngularServerApp({
48+
allowStaticRouteRender: true,
49+
});
50+
4851
// Only Add the transform hook only if it's a different instance.
4952
if (cachedAngularServerApp !== angularServerApp) {
5053
angularServerApp.hooks.on('html:transform:pre', async ({ html, url }) => {
@@ -96,6 +99,7 @@ export async function createAngularSsrExternalMiddleware(
9699
reqHandler?: unknown;
97100
AngularAppEngine: typeof SSRAngularAppEngine;
98101
};
102+
99103
if (!isSsrNodeRequestHandler(reqHandler) && !isSsrRequestHandler(reqHandler)) {
100104
if (!fallbackWarningShown) {
101105
// eslint-disable-next-line no-console
@@ -118,6 +122,7 @@ export async function createAngularSsrExternalMiddleware(
118122
}
119123

120124
if (cachedAngularAppEngine !== AngularAppEngine) {
125+
AngularAppEngine.ɵallowStaticRouteRender = true;
121126
AngularAppEngine.ɵhooks.on('html:transform:pre', async ({ html, url }) => {
122127
const processedHtml = await server.transformIndexHtml(url.pathname, html);
123128

packages/angular/build/src/utils/server-rendering/prerender.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ async function getAllRoutes(
280280

281281
if (appShellOptions) {
282282
routes.push({
283+
renderMode: RouteRenderMode.AppShell,
283284
route: urlJoin(baseHref, appShellOptions.route),
284285
});
285286
}
@@ -288,6 +289,7 @@ async function getAllRoutes(
288289
const routesFromFile = (await readFile(routesFile, 'utf8')).split(/\r?\n/);
289290
for (const route of routesFromFile) {
290291
routes.push({
292+
renderMode: RouteRenderMode.Prerender,
291293
route: urlJoin(baseHref, route.trim()),
292294
});
293295
}
@@ -321,7 +323,19 @@ async function getAllRoutes(
321323
{},
322324
);
323325

324-
return { errors, serializedRouteTree: [...routes, ...serializedRouteTree] };
326+
if (!routes.length) {
327+
return { errors, serializedRouteTree };
328+
}
329+
330+
// Merge the routing trees
331+
const uniqueRoutes = new Map();
332+
for (const item of [...routes, ...serializedRouteTree]) {
333+
if (!uniqueRoutes.has(item.route)) {
334+
uniqueRoutes.set(item.route, item);
335+
}
336+
}
337+
338+
return { errors, serializedRouteTree: Array.from(uniqueRoutes.values()) };
325339
} catch (err) {
326340
assertIsError(err);
327341

packages/angular/build/src/utils/server-rendering/render-worker.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,13 @@ let serverURL = DEFAULT_URL;
3939
async function renderPage({ url }: RenderOptions): Promise<string | null> {
4040
const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } =
4141
await loadEsmModuleFromMemory('./main.server.mjs');
42-
const angularServerApp = getOrCreateAngularServerApp();
43-
const response = await angularServerApp.renderStatic(
44-
new URL(url, serverURL),
45-
AbortSignal.timeout(30_000),
42+
43+
const angularServerApp = getOrCreateAngularServerApp({
44+
allowStaticRouteRender: true,
45+
});
46+
47+
const response = await angularServerApp.handle(
48+
new Request(new URL(url, serverURL), { signal: AbortSignal.timeout(30_000) }),
4649
);
4750

4851
return response ? response.text() : null;

packages/angular/ssr/src/app-engine.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import type { AngularServerApp } from './app';
9+
import type { AngularServerApp, getOrCreateAngularServerApp } from './app';
1010
import { Hooks } from './hooks';
1111
import { getPotentialLocaleIdFromUrl } from './i18n';
1212
import { EntryPointExports, getAngularAppEngineManifest } from './manifest';
13-
import { stripIndexHtmlFromURL, stripTrailingSlash } from './utils/url';
1413

1514
/**
1615
* Angular server application engine.
@@ -24,23 +23,23 @@ import { stripIndexHtmlFromURL, stripTrailingSlash } from './utils/url';
2423
*/
2524
export class AngularAppEngine {
2625
/**
27-
* Hooks for extending or modifying the behavior of the server application.
28-
* These hooks are used by the Angular CLI when running the development server and
29-
* provide extensibility points for the application lifecycle.
26+
* A flag to enable or disable the rendering of prerendered routes.
27+
*
28+
* Typically used during development to avoid prerendering all routes ahead of time,
29+
* allowing them to be rendered on the fly as requested.
3030
*
3131
* @private
3232
*/
33-
static ɵhooks = /* #__PURE__*/ new Hooks();
33+
static ɵallowStaticRouteRender = false;
3434

3535
/**
36-
* Provides access to the hooks for extending or modifying the server application's behavior.
37-
* This allows attaching custom functionality to various server application lifecycle events.
36+
* Hooks for extending or modifying the behavior of the server application.
37+
* These hooks are used by the Angular CLI when running the development server and
38+
* provide extensibility points for the application lifecycle.
3839
*
39-
* @internal
40+
* @private
4041
*/
41-
get hooks(): Hooks {
42-
return AngularAppEngine.ɵhooks;
43-
}
42+
static ɵhooks = /* #__PURE__*/ new Hooks();
4443

4544
/**
4645
* The manifest for the server application.
@@ -88,12 +87,15 @@ export class AngularAppEngine {
8887
return null;
8988
}
9089

91-
const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = entryPoint;
9290
// Note: Using `instanceof` is not feasible here because `AngularServerApp` will
9391
// be located in separate bundles, making `instanceof` checks unreliable.
94-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
95-
const serverApp = getOrCreateAngularServerApp() as AngularServerApp;
96-
serverApp.hooks = this.hooks;
92+
const ɵgetOrCreateAngularServerApp =
93+
entryPoint.ɵgetOrCreateAngularServerApp as typeof getOrCreateAngularServerApp;
94+
95+
const serverApp = ɵgetOrCreateAngularServerApp({
96+
allowStaticRouteRender: AngularAppEngine.ɵallowStaticRouteRender,
97+
hooks: AngularAppEngine.ɵhooks,
98+
});
9799

98100
return serverApp;
99101
}

0 commit comments

Comments
 (0)