diff --git a/packages/angular_devkit/build_angular/src/tools/esbuild/application-code-bundle.ts b/packages/angular_devkit/build_angular/src/tools/esbuild/application-code-bundle.ts index 7ad66cf5800c..5e74d53f4934 100644 --- a/packages/angular_devkit/build_angular/src/tools/esbuild/application-code-bundle.ts +++ b/packages/angular_devkit/build_angular/src/tools/esbuild/application-code-bundle.ts @@ -278,6 +278,7 @@ export function createServerCodeBundleOptions( `import moduleOrBootstrapFn from './${mainServerEntryPoint}';`, `export default moduleOrBootstrapFn;`, `export * from './${mainServerEntryPoint}';`, + `export { ɵConsole } from '@angular/core';`, `export { renderApplication, renderModule, ɵSERVER_CONTEXT } from '@angular/platform-server';`, ]; diff --git a/packages/angular_devkit/build_angular/src/utils/routes-extractor/extractor.ts b/packages/angular_devkit/build_angular/src/utils/routes-extractor/extractor.ts index c70ee662e0b2..5e4ecdfef35e 100644 --- a/packages/angular_devkit/build_angular/src/utils/routes-extractor/extractor.ts +++ b/packages/angular_devkit/build_angular/src/utils/routes-extractor/extractor.ts @@ -14,6 +14,7 @@ import { createPlatformFactory, platformCore, ɵwhenStable as whenStable, + ɵConsole, } from '@angular/core'; import { INITIAL_CONFIG, @@ -79,12 +80,26 @@ export async function* extractRoutes( document: string, ): AsyncIterableIterator { const platformRef = createPlatformFactory(platformCore, 'server', [ - [ - { - provide: INITIAL_CONFIG, - useValue: { document, url: '' }, + { + provide: INITIAL_CONFIG, + useValue: { document, url: '' }, + }, + { + provide: ɵConsole, + /** An Angular Console Provider that does not print a set of predefined logs. */ + useFactory: () => { + class Console extends ɵConsole { + private readonly ignoredLogs = new Set(['Angular is running in development mode.']); + override log(message: string): void { + if (!this.ignoredLogs.has(message)) { + super.log(message); + } + } + } + + return new Console(); }, - ], + }, ...INTERNAL_SERVER_PLATFORM_PROVIDERS, ])(); diff --git a/packages/angular_devkit/build_angular/src/utils/server-rendering/main-bundle-exports.ts b/packages/angular_devkit/build_angular/src/utils/server-rendering/main-bundle-exports.ts index b212182cd37c..7847e7eb1a84 100644 --- a/packages/angular_devkit/build_angular/src/utils/server-rendering/main-bundle-exports.ts +++ b/packages/angular_devkit/build_angular/src/utils/server-rendering/main-bundle-exports.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import type { ApplicationRef, Type } from '@angular/core'; +import type { ApplicationRef, Type, ɵConsole } from '@angular/core'; import type { renderApplication, renderModule, ɵSERVER_CONTEXT } from '@angular/platform-server'; import type { extractRoutes } from '../routes-extractor/extractor'; @@ -27,4 +27,7 @@ export interface MainServerBundleExports { extractRoutes: typeof extractRoutes; ɵresetCompiledComponents?: () => void; + + /** Angular Console token/class. */ + ɵConsole: typeof ɵConsole; } diff --git a/packages/angular_devkit/build_angular/src/utils/server-rendering/render-page.ts b/packages/angular_devkit/build_angular/src/utils/server-rendering/render-page.ts index 756ecf368c14..58bc6c676c91 100644 --- a/packages/angular_devkit/build_angular/src/utils/server-rendering/render-page.ts +++ b/packages/angular_devkit/build_angular/src/utils/server-rendering/render-page.ts @@ -11,7 +11,6 @@ import { basename } from 'node:path'; import { InlineCriticalCssProcessor } from '../index-file/inline-critical-css'; import { loadEsmModule } from '../load-esm'; import { MainServerBundleExports } from './main-bundle-exports'; -import { patchConsoleToIgnoreSpecificLogs } from './utils'; export interface RenderOptions { route: string; @@ -47,6 +46,7 @@ export async function renderPage({ renderModule, renderApplication, ɵresetCompiledComponents, + ɵConsole, } = await loadBundle('./main.server.mjs'); // Need to clean up GENERATED_COMP_IDS map in `@angular/core`. @@ -59,27 +59,38 @@ export async function renderPage({ provide: ɵSERVER_CONTEXT, useValue: serverContext, }, + { + provide: ɵConsole, + /** An Angular Console Provider that does not print a set of predefined logs. */ + useFactory: () => { + class Console extends ɵConsole { + private readonly ignoredLogs = new Set(['Angular is running in development mode.']); + override log(message: string): void { + if (!this.ignoredLogs.has(message)) { + super.log(message); + } + } + } + + return new Console(); + }, + }, ]; let html: string | undefined; - const resetPatchedConsole = patchConsoleToIgnoreSpecificLogs(); - try { - if (isBootstrapFn(bootstrapAppFnOrModule)) { - html = await renderApplication(bootstrapAppFnOrModule, { - document, - url: route, - platformProviders, - }); - } else { - html = await renderModule(bootstrapAppFnOrModule, { - document, - url: route, - extraProviders: platformProviders, - }); - } - } finally { - resetPatchedConsole(); + if (isBootstrapFn(bootstrapAppFnOrModule)) { + html = await renderApplication(bootstrapAppFnOrModule, { + document, + url: route, + platformProviders, + }); + } else { + html = await renderModule(bootstrapAppFnOrModule, { + document, + url: route, + extraProviders: platformProviders, + }); } if (inlineCriticalCss) { diff --git a/packages/angular_devkit/build_angular/src/utils/server-rendering/routes-extractor-worker.ts b/packages/angular_devkit/build_angular/src/utils/server-rendering/routes-extractor-worker.ts index 8c18b1871816..1b4c71bd33b1 100644 --- a/packages/angular_devkit/build_angular/src/utils/server-rendering/routes-extractor-worker.ts +++ b/packages/angular_devkit/build_angular/src/utils/server-rendering/routes-extractor-worker.ts @@ -10,7 +10,6 @@ import { workerData } from 'node:worker_threads'; import { loadEsmModule } from '../load-esm'; import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks'; import { MainServerBundleExports } from './main-bundle-exports'; -import { patchConsoleToIgnoreSpecificLogs } from './utils'; export interface RoutesExtractorWorkerData extends ESMInMemoryFileLoaderWorkerData { document: string; @@ -28,8 +27,6 @@ export interface RoutersExtractorWorkerResult { const { document, verbose } = workerData as RoutesExtractorWorkerData; export default async function (): Promise { - patchConsoleToIgnoreSpecificLogs(); - const { default: bootstrapAppFnOrModule, extractRoutes } = await loadEsmModule('./main.server.mjs'); diff --git a/packages/angular_devkit/build_angular/src/utils/server-rendering/utils.ts b/packages/angular_devkit/build_angular/src/utils/server-rendering/utils.ts deleted file mode 100644 index 3e467af24930..000000000000 --- a/packages/angular_devkit/build_angular/src/utils/server-rendering/utils.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -const IGNORED_LOGS = new Set(['Angular is running in development mode.']); -const PATCHED_CONSOLE_SYMBOL = Symbol.for('Angular CLI Console Patched'); - -/** Method to filter a number of console.log from the output. - * @returns a function that when invoked restores the default console.log behaviour. - */ -export function patchConsoleToIgnoreSpecificLogs(): () => void { - /* eslint-disable no-console, @typescript-eslint/no-explicit-any */ - if (!(console as any)[PATCHED_CONSOLE_SYMBOL]) { - const originalConsoleLog = console.log; - - console.log = (...args) => { - if (!IGNORED_LOGS.has(args[0])) { - originalConsoleLog.apply(args); - } - }; - - (console as any)[PATCHED_CONSOLE_SYMBOL] = () => { - console.log = originalConsoleLog; - delete (console as any)[PATCHED_CONSOLE_SYMBOL]; - }; - } - - return (console as any)[PATCHED_CONSOLE_SYMBOL]; - /* eslint-enable no-console, @typescript-eslint/no-explicit-any */ -}