Skip to content

Commit e73e910

Browse files
committed
fix(@angular/build): handle empty module case to avoid TypeError
Ensure that accessing the module after invalidation doesn't result in an empty module, which causes a `TypeError: ɵgetOrCreateAngularServerApp is not a function`. Closes #29458 (cherry picked from commit 8e884a0)
1 parent e1c8e05 commit e73e910

File tree

2 files changed

+16
-16
lines changed

2 files changed

+16
-16
lines changed

packages/angular/build/src/builders/dev-server/vite-server.ts

+11-16
Original file line numberDiff line numberDiff line change
@@ -501,35 +501,30 @@ async function invalidateUpdatedFiles(
501501
}
502502

503503
// Invalidate any updated files
504-
let destroyAngularServerAppCalled = false;
504+
let serverApplicationChanged = false;
505505
for (const [file, record] of generatedFiles) {
506506
if (!record.updated) {
507507
continue;
508508
}
509-
record.updated = false;
510-
511-
if (record.type === BuildOutputFileType.ServerApplication && !destroyAngularServerAppCalled) {
512-
// Clear the server app cache
513-
// This must be done before module invalidation.
514-
const { ɵdestroyAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs')) as {
515-
ɵdestroyAngularServerApp: typeof destroyAngularServerApp;
516-
};
517-
518-
ɵdestroyAngularServerApp();
519-
destroyAngularServerAppCalled = true;
520-
}
521509

510+
record.updated = false;
522511
updatedFiles.push(file);
512+
serverApplicationChanged ||= record.type === BuildOutputFileType.ServerApplication;
523513

524514
const updatedModules = server.moduleGraph.getModulesByFile(
525515
normalizePath(join(server.config.root, file)),
526516
);
527517
updatedModules?.forEach((m) => server.moduleGraph.invalidateModule(m));
528518
}
529519

530-
if (destroyAngularServerAppCalled) {
531-
// Trigger module evaluation before reload to initiate dependency optimization.
532-
await server.ssrLoadModule('/main.server.mjs');
520+
if (serverApplicationChanged) {
521+
// Clear the server app cache and
522+
// trigger module evaluation before reload to initiate dependency optimization.
523+
const { ɵdestroyAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs')) as {
524+
ɵdestroyAngularServerApp: typeof destroyAngularServerApp;
525+
};
526+
527+
ɵdestroyAngularServerApp();
533528
}
534529

535530
return updatedFiles;

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

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ export function createAngularSsrInternalMiddleware(
4040
const { writeResponseToNodeResponse, createWebRequestFromNodeRequest } =
4141
await loadEsmModule<typeof import('@angular/ssr/node')>('@angular/ssr/node');
4242

43+
// The following is necessary because accessing the module after invalidation may result in an empty module,
44+
// which can trigger a `TypeError: ɵgetOrCreateAngularServerApp is not a function` error.
45+
// TODO: look into why.
46+
await server.ssrLoadModule('/main.server.mjs');
47+
4348
const { ɵgetOrCreateAngularServerApp } = (await server.ssrLoadModule('/main.server.mjs')) as {
4449
ɵgetOrCreateAngularServerApp: typeof getOrCreateAngularServerApp;
4550
};

0 commit comments

Comments
 (0)