From 5f66ff4cc0c0ef7c03871998829bde56f9257c26 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 15 Aug 2024 07:01:14 +0000 Subject: [PATCH] fix(@angular/build): improve error message when an unhandled exception occurs during prerendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change enhances the error messaging when an unhandled exception occurs during the prerendering process. The updated error message provides more context and clarity. **Previous Behavior** ``` ng b An unhandled exception occurred: Some error!!! See "/tmp/ng-S2ABKF/angular-errors.log" for further details. ``` **Updated Behavior:** ``` ng b Browser bundles Initial chunk files | Names | Raw size | Estimated transfer size main-AFPIPGGK.js | main | 218.00 kB | 59.48 kB polyfills-Z2GOM3BN.js | polyfills | 35.82 kB | 11.80 kB styles-5INURTSO.css | styles | 0 bytes | 0 bytes | Initial total | 253.82 kB | 71.28 kB Server bundles Initial chunk files | Names | Raw size server.mjs | server | 1.11 MB | chunk-HZL5H5M5.mjs | - | 526.77 kB | polyfills.server.mjs | polyfills.server | 269.91 kB | chunk-GFWAPST7.mjs | - | 19.16 kB | chunk-5XUXGTUW.mjs | - | 2.55 kB | render-utils.server.mjs | render-utils.server | 1.46 kB | main.server.mjs | main.server | 149 bytes | Lazy chunk files | Names | Raw size chunk-7YC4RJ5P.mjs | xhr2 | 12.08 kB | Prerendered 1 static route. Application bundle generation failed. [4.923 seconds] ✘ [ERROR] An error occurred while prerendering route '/'. Error: Some error!!! at render (node_modules/@angular/build/src/utils/server-rendering/render-worker.js:20:20) at /angular-cli/abc/node_modules/piscina/dist/worker.js:146:32 ``` Closes #28212 --- .../src/utils/server-rendering/prerender.ts | 57 ++++++++++++------- .../tests/behavior/build-errors_spec.ts | 5 +- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/packages/angular/build/src/utils/server-rendering/prerender.ts b/packages/angular/build/src/utils/server-rendering/prerender.ts index 5b42f8c739ef..f8796a7ac861 100644 --- a/packages/angular/build/src/utils/server-rendering/prerender.ts +++ b/packages/angular/build/src/utils/server-rendering/prerender.ts @@ -81,7 +81,11 @@ export async function prerenderPages( } // Get routes to prerender - const { routes: allRoutes, warnings: routesWarnings } = await getAllRoutes( + const { + routes: allRoutes, + warnings: routesWarnings, + errors: routesErrors, + } = await getAllRoutes( workspaceRoot, outputFilesForWorker, assetsReversed, @@ -92,11 +96,15 @@ export async function prerenderPages( verbose, ); + if (routesErrors?.length) { + errors.push(...routesErrors); + } + if (routesWarnings?.length) { warnings.push(...routesWarnings); } - if (allRoutes.size < 1) { + if (allRoutes.size < 1 || errors.length > 0) { return { errors, warnings, @@ -190,22 +198,27 @@ async function renderPages( const isAppShellRoute = appShellRoute === route; const serverContext: ServerContext = isAppShellRoute ? 'app-shell' : 'ssg'; const render: Promise = renderWorker.run({ route, serverContext }); - const renderResult: Promise = render.then(({ content, warnings, errors }) => { - if (content !== undefined) { - const outPath = isAppShellRoute - ? 'index.html' - : posix.join(removeLeadingSlash(route), 'index.html'); - output[outPath] = content; - } - - if (warnings) { - warnings.push(...warnings); - } - - if (errors) { - errors.push(...errors); - } - }); + const renderResult: Promise = render + .then(({ content, warnings, errors }) => { + if (content !== undefined) { + const outPath = isAppShellRoute + ? 'index.html' + : posix.join(removeLeadingSlash(route), 'index.html'); + output[outPath] = content; + } + + if (warnings) { + warnings.push(...warnings); + } + + if (errors) { + errors.push(...errors); + } + }) + .catch((err) => { + errors.push(`An error occurred while prerendering route '${route}'.\n\n${err.stack}`); + void renderWorker.destroy(); + }); renderingPromises.push(renderResult); } @@ -231,7 +244,7 @@ async function getAllRoutes( prerenderOptions: PrerenderOptions, sourcemap: boolean, verbose: boolean, -): Promise<{ routes: Set; warnings?: string[] }> { +): Promise<{ routes: Set; warnings?: string[]; errors?: string[] }> { const { routesFile, discoverRoutes } = prerenderOptions; const routes = new RoutesSet(); const { route: appShellRoute } = appShellOptions; @@ -275,8 +288,12 @@ async function getAllRoutes( recordTiming: false, }); + const errors: string[] = []; const { routes: extractedRoutes, warnings }: RoutersExtractorWorkerResult = await renderWorker .run({}) + .catch((err) => { + errors.push(`An error occurred while extracting routes.\n\n${err.stack}`); + }) .finally(() => { void renderWorker.destroy(); }); @@ -285,7 +302,7 @@ async function getAllRoutes( routes.add(route); } - return { routes, warnings }; + return { routes, warnings, errors }; } function addLeadingSlash(value: string): string { diff --git a/packages/angular_devkit/build_angular/src/builders/server/tests/behavior/build-errors_spec.ts b/packages/angular_devkit/build_angular/src/builders/server/tests/behavior/build-errors_spec.ts index 0fbb12794a62..11bd6b94b25e 100644 --- a/packages/angular_devkit/build_angular/src/builders/server/tests/behavior/build-errors_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/server/tests/behavior/build-errors_spec.ts @@ -15,13 +15,14 @@ describeBuilder(execute, SERVER_BUILDER_INFO, (harness) => { it('emits errors', async () => { harness.useTarget('server', { ...BASE_OPTIONS, - watch: true, }); // Generate an error await harness.appendToFile('src/main.server.ts', `const foo: = 'abc';`); - const { result, logs } = await harness.executeOnce(); + const { result, logs } = await harness.executeOnce({ + outputLogsOnFailure: false, + }); expect(result?.success).toBeFalse(); expect(logs).toContain(