Skip to content

refactor(@angular-devkit/build-angular): properly display errors originating in ESM loader hooks #27263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @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
*/

import { assertIsError } from '../error';
import { loadEsmModule } from '../load-esm';
import { MainServerBundleExports, RenderUtilsServerBundleExports } from './main-bundle-exports';

export function loadEsmModuleFromMemory(
path: './main.server.mjs',
): Promise<MainServerBundleExports>;
export function loadEsmModuleFromMemory(
path: './render-utils.server.mjs',
): Promise<RenderUtilsServerBundleExports>;
export function loadEsmModuleFromMemory(path: string): Promise<unknown> {
return loadEsmModule(new URL(path, 'memory://')).catch((e) => {
assertIsError(e);

// While the error is an 'instanceof Error', it is extended with non transferable properties
// and cannot be transferred from a worker when using `--import`. This results in the error object
// displaying as '[Object object]' when read outside of the worker. Therefore, we reconstruct the error message here.
const error: Error & { code?: string } = new Error(e.message);
error.stack = e.stack;
error.name = e.name;
error.code = e.code;

throw error;
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import type { ApplicationRef, StaticProvider } from '@angular/core';
import assert from 'node:assert';
import { basename } from 'node:path';
import { loadEsmModule } from '../load-esm';
import { loadEsmModuleFromMemory } from './load-esm-from-memory';
import { MainServerBundleExports, RenderUtilsServerBundleExports } from './main-bundle-exports';

export interface RenderOptions {
Expand Down Expand Up @@ -39,7 +39,7 @@ export async function renderPage({
document,
inlineCriticalCss,
outputFiles,
loadBundle = loadEsmModule,
loadBundle = loadEsmModuleFromMemory,
}: RenderOptions): Promise<RenderResult> {
const { default: bootstrapAppFnOrModule } = await loadBundle('./main.server.mjs');
const { ɵSERVER_CONTEXT, renderModule, renderApplication, ɵresetCompiledComponents, ɵConsole } =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/

import { workerData } from 'node:worker_threads';
import { loadEsmModule } from '../load-esm';
import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
import { patchFetchToLoadInMemoryAssets } from './fetch-patch';
import { RenderResult, ServerContext, renderPage } from './render-page';
Expand Down Expand Up @@ -35,7 +34,6 @@ function render(options: RenderOptions): Promise<RenderResult> {
outputFiles,
document,
inlineCriticalCss,
loadBundle: async (path) => await loadEsmModule(new URL(path, 'memory://')),
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
*/

import { workerData } from 'node:worker_threads';
import { loadEsmModule } from '../load-esm';
import type { ESMInMemoryFileLoaderWorkerData } from './esm-in-memory-loader/loader-hooks';
import { patchFetchToLoadInMemoryAssets } from './fetch-patch';
import { MainServerBundleExports, RenderUtilsServerBundleExports } from './main-bundle-exports';
import { loadEsmModuleFromMemory } from './load-esm-from-memory';

export interface RoutesExtractorWorkerData extends ESMInMemoryFileLoaderWorkerData {
document: string;
Expand All @@ -30,12 +29,8 @@ const { document, verbose } = workerData as RoutesExtractorWorkerData;

/** Renders an application based on a provided options. */
async function extractRoutes(): Promise<RoutersExtractorWorkerResult> {
const { extractRoutes } = await loadEsmModule<RenderUtilsServerBundleExports>(
new URL('./render-utils.server.mjs', 'memory://'),
);
const { default: bootstrapAppFnOrModule } = await loadEsmModule<MainServerBundleExports>(
new URL('./main.server.mjs', 'memory://'),
);
const { extractRoutes } = await loadEsmModuleFromMemory('./render-utils.server.mjs');
const { default: bootstrapAppFnOrModule } = await loadEsmModuleFromMemory('./main.server.mjs');

const skippedRedirects: string[] = [];
const skippedOthers: string[] = [];
Expand Down