Skip to content

Commit

Permalink
fixup! fix(@angular/ssr): enable serving of prerendered pages in the …
Browse files Browse the repository at this point in the history
…App Engine
  • Loading branch information
alan-agius4 committed Oct 31, 2024
1 parent 1f60d7c commit e640320
Show file tree
Hide file tree
Showing 19 changed files with 219 additions and 262 deletions.
4 changes: 1 addition & 3 deletions goldens/public-api/angular/ssr/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import { EnvironmentProviders } from '@angular/core';

// @public
export class AngularAppEngine {
process(request: Request, requestContext?: unknown): Promise<Response | null>;
render(request: Request, requestContext?: unknown): Promise<Response | null>;
serve(request: Request): Promise<Response | null>;
handle(request: Request, requestContext?: unknown): Promise<Response | null>;
static ɵhooks: Hooks;
}

Expand Down
4 changes: 1 addition & 3 deletions goldens/public-api/angular/ssr/node/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import { Type } from '@angular/core';

// @public
export class AngularNodeAppEngine {
process(request: IncomingMessage, requestContext?: unknown): Promise<Response | null>;
render(request: IncomingMessage, requestContext?: unknown): Promise<Response | null>;
serve(request: IncomingMessage): Promise<Response | null>;
handle(request: IncomingMessage, requestContext?: unknown): Promise<Response | null>;
}

// @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ export async function executePostBundleSteps(
}
case RouteRenderMode.Server:
case RouteRenderMode.Client:
case RouteRenderMode.AppShell:
serializableRouteTreeNodeForManifest.push(metadata);

break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function createAngularSsrInternalMiddleware(
const webReq = new Request(createWebRequestFromNodeRequest(req), {
signal: AbortSignal.timeout(30_000),
});
const webRes = await angularServerApp.render(webReq);
const webRes = await angularServerApp.handle(webReq);
if (!webRes) {
return next();
}
Expand Down
6 changes: 3 additions & 3 deletions packages/angular/build/src/utils/server-rendering/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { extname } from 'node:path';
import {
INDEX_HTML_CSR,
INDEX_HTML_SERVER,
NormalizedApplicationBuildOptions,
getLocaleBaseHref,
} from '../../builders/application/options';
Expand Down Expand Up @@ -135,7 +134,8 @@ export function generateAngularServerAppManifest(
): string {
const serverAssetsContent: string[] = [];
for (const file of [...additionalHtmlOutputFiles.values(), ...outputFiles]) {
if (file.path.endsWith('.html') || (inlineCriticalCss && file.path.endsWith('.css'))) {
const extension = extname(file.path);
if (extension === '.html' || (inlineCriticalCss && extension === '.css')) {
serverAssetsContent.push(`['${file.path}', async () => \`${escapeUnsafeChars(file.text)}\`]`);
}
}
Expand Down
40 changes: 2 additions & 38 deletions packages/angular/ssr/node/src/app-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,6 @@ import { createWebRequestFromNodeRequest } from './request';
export class AngularNodeAppEngine {
private readonly angularAppEngine = new AngularAppEngine();

/**
* Renders an HTTP response based on the incoming request using the Angular server application.
*
* The method processes the incoming request, determines the appropriate route, and prepares the
* rendering context to generate a response. If the request URL corresponds to a static file (excluding `/index.html`),
* the method returns `null`.
*
* Example: A request to `https://www.example.com/page/index.html` will render the Angular route
* associated with `https://www.example.com/page`.
*
* @param request - The incoming HTTP request object to be rendered.
* @param requestContext - Optional additional context for the request, such as metadata or custom settings.
* @returns A promise that resolves to a `Response` object, or `null` if the request URL is for a static file
* (e.g., `./logo.png`) rather than an application route.
*/
render(request: IncomingMessage, requestContext?: unknown): Promise<Response | null> {
return this.angularAppEngine.render(createWebRequestFromNodeRequest(request), requestContext);
}

/**
* Serves a prerendered page for a given request.
*
* This method examines the incoming request to determine if it corresponds to a known prerendered page.
* If a matching page is found, it returns a `Response` object containing the page content; otherwise, it returns `null`.
*
* @param request - The incoming HTTP request for a prerendered page.
* @returns A promise that resolves to a `Response` object containing the prerendered page content, or `null`
* if no matching page is found.
*/
serve(request: IncomingMessage): Promise<Response | null> {
return this.angularAppEngine.serve(createWebRequestFromNodeRequest(request));
}

/**
* Handles incoming HTTP requests by serving prerendered content or rendering the page.
*
Expand All @@ -68,12 +35,9 @@ export class AngularNodeAppEngine {
* @returns A promise that resolves to the HTTP response object resulting from the request handling,
* or null if no matching content is found.
*/
async process(request: IncomingMessage, requestContext?: unknown): Promise<Response | null> {
async handle(request: IncomingMessage, requestContext?: unknown): Promise<Response | null> {
const webRequest = createWebRequestFromNodeRequest(request);

return (
(await this.angularAppEngine.serve(webRequest)) ??
(await this.angularAppEngine.render(webRequest, requestContext))
);
return this.angularAppEngine.handle(webRequest, requestContext);
}
}
44 changes: 2 additions & 42 deletions packages/angular/ssr/src/app-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,43 +52,6 @@ export class AngularAppEngine {
*/
private readonly entryPointsCache = new Map<string, Promise<EntryPointExports>>();

/**
* Renders a response for the given HTTP request using the server application.
*
* This method processes the request, determines the appropriate route and rendering context,
* and returns an HTTP response.
*
* If the request URL appears to be for a file (excluding `/index.html`), the method returns `null`.
* A request to `https://www.example.com/page/index.html` will render the Angular route
* corresponding to `https://www.example.com/page`.
*
* @param request - The incoming HTTP request object to be rendered.
* @param requestContext - Optional additional context for the request, such as metadata.
* @returns A promise that resolves to a Response object, or `null` if the request URL represents a file (e.g., `./logo.png`)
* rather than an application route.
*/
async render(request: Request, requestContext?: unknown): Promise<Response | null> {
const serverApp = await this.getAngularServerAppForRequest(request);

return serverApp ? serverApp.render(request, requestContext) : null;
}

/**
* Serves a prerendered page for a given request.
*
* This method examines the incoming request to determine if it corresponds to a known prerendered page.
* If a matching page is found, it returns a `Response` object containing the page content; otherwise, it returns `null`.
*
* @param request - The incoming HTTP request object to be rendered.
* @returns A promise that resolves to a `Response` object containing the prerendered page content, or `null`
* if no matching page is found.
**/
async serve(request: Request): Promise<Response | null> {
const serverApp = await this.getAngularServerAppForRequest(request);

return serverApp ? serverApp.serve(request) : null;
}

/**
* Handles incoming HTTP requests by serving prerendered content or rendering the page.
*
Expand All @@ -101,13 +64,10 @@ export class AngularAppEngine {
* @returns A promise that resolves to the HTTP response object resulting from the request handling,
* or null if no matching content is found.
*/
async process(request: Request, requestContext?: unknown): Promise<Response | null> {
async handle(request: Request, requestContext?: unknown): Promise<Response | null> {
const serverApp = await this.getAngularServerAppForRequest(request);
if (!serverApp) {
return null;
}

return (await serverApp.serve(request)) ?? (await serverApp.render(request, requestContext));
return serverApp ? serverApp.handle(request, requestContext) : null;
}

/**
Expand Down
Loading

0 comments on commit e640320

Please sign in to comment.