From f6ed31fdf2fe0f2a73f09c39e82e4b6bd6ccc6a6 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 12 Oct 2021 11:55:53 +0200 Subject: [PATCH] fix(@schematics/angular): wrap bootstrapping code in an HMR compatible manner With this change we update the universal schematic bootstrap code to handle HMR properly. Previously, the bootstrapping code was called only on `DOMContentLoaded` which is not triggered when running in HMR. Closes #21932 (cherry picked from commit 08687d147552be1a1fe97447f2d16d2bb4ba3df5) --- packages/schematics/angular/universal/index.ts | 18 +++++++++++++----- .../schematics/angular/universal/index_spec.ts | 6 ++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/schematics/angular/universal/index.ts b/packages/schematics/angular/universal/index.ts index 6a1b38f49d61..7af96ced1115 100644 --- a/packages/schematics/angular/universal/index.ts +++ b/packages/schematics/angular/universal/index.ts @@ -141,9 +141,17 @@ function wrapBootstrapCall(mainFile: string): Rule { // indent contents const triviaWidth = bootstrapCall.getLeadingTriviaWidth(); const beforeText = - `document.addEventListener('DOMContentLoaded', () => {\n` + - ' '.repeat(triviaWidth > 2 ? triviaWidth + 1 : triviaWidth); - const afterText = `\n${triviaWidth > 2 ? ' '.repeat(triviaWidth - 1) : ''}});`; + `function bootstrap() {\n` + ' '.repeat(triviaWidth > 2 ? triviaWidth + 1 : triviaWidth); + const afterText = + `\n${triviaWidth > 2 ? ' '.repeat(triviaWidth - 1) : ''}};\n` + + ` + +if (document.readyState === 'complete') { + bootstrap(); +} else { + document.addEventListener('DOMContentLoaded', bootstrap); +} +`; // in some cases we need to cater for a trailing semicolon such as; // bootstrap().catch(err => console.log(err)); @@ -236,8 +244,8 @@ export default function (options: UniversalOptions): Rule { throw targetBuildNotFoundError(); } - const clientBuildOptions = ((clientBuildTarget.options || - {}) as unknown) as BrowserBuilderOptions; + const clientBuildOptions = (clientBuildTarget.options || + {}) as unknown as BrowserBuilderOptions; const clientTsConfig = normalize(clientBuildOptions.tsConfig); const tsConfigExtends = basename(clientTsConfig); diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts index d634dd66a5cd..178bf8e0a491 100644 --- a/packages/schematics/angular/universal/index_spec.ts +++ b/packages/schematics/angular/universal/index_spec.ts @@ -191,7 +191,7 @@ describe('Universal Schematic', () => { .toPromise(); const filePath = '/projects/bar/src/main.ts'; const contents = tree.readContent(filePath); - expect(contents).toMatch(/document.addEventListener\('DOMContentLoaded', \(\) => {/); + expect(contents).toContain(`document.addEventListener('DOMContentLoaded', bootstrap);`); }); it('should wrap the bootstrap declaration in a DOMContentLoaded event handler', async () => { @@ -221,9 +221,7 @@ describe('Universal Schematic', () => { .runSchematicAsync('universal', defaultOptions, appTree) .toPromise(); const contents = tree.readContent(filePath); - expect(contents).toMatch( - /document.addEventListener\('DOMContentLoaded', \(\) => {[\n\r\s]+bootstrap\(\)/, - ); + expect(contents).toContain(`document.addEventListener('DOMContentLoaded', bootstrap);`); }); it('should install npm dependencies', async () => {