From da74c6e65baa01a6d1e00aed94de27a5b9527a26 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Mon, 5 Jul 2021 09:24:03 +0200 Subject: [PATCH 1/3] Revert "fix(@angular-devkit/build-angular): control linker template sourcemapping via builder sourcemap options" This reverts commit d4c5f8518d4801b9fd76de289a015dcbb8d8f69b. Following a debugging and investigation with @petebacondarwin it appears that when the external template handling in the linker generates Babel AST nodes that reference the external template files which breaks Babel when it tried to flatten final source-map, which ends up no emitting any source-maps. As an interim solution we should revert this. Closes #21271 --- .../build_angular/src/babel/presets/application.ts | 2 -- .../build_angular/src/babel/webpack-loader.ts | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/babel/presets/application.ts b/packages/angular_devkit/build_angular/src/babel/presets/application.ts index c34c5431e4f0..5a092f6d89a9 100644 --- a/packages/angular_devkit/build_angular/src/babel/presets/application.ts +++ b/packages/angular_devkit/build_angular/src/babel/presets/application.ts @@ -20,7 +20,6 @@ export interface ApplicationPresetOptions { angularLinker?: { shouldLink: boolean; jitMode: boolean; - sourcemap: boolean; }; forceES5?: boolean; @@ -138,7 +137,6 @@ export default function (api: unknown, options: ApplicationPresetOptions) { plugins.push( createEs2015LinkerPlugin({ linkerJitMode: options.angularLinker.jitMode, - sourceMapping: options.angularLinker.sourcemap, logger: createNgtscLogger(options.diagnosticReporter), fileSystem: { resolve: path.resolve, diff --git a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts index dbbc248b1045..ba6b2583e1c3 100644 --- a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts +++ b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts @@ -58,7 +58,6 @@ export default custom(() => { customOptions.angularLinker = { shouldLink: true, jitMode: aot !== true, - sourcemap: false, }; shouldProcess = true; } @@ -141,15 +140,6 @@ export default custom(() => { ); } - // Only enable linker template sourcemapping if linker is enabled and Webpack provides - // a sourcemap. This logic allows the linker sourcemap behavior to be controlled by the - // Webpack sourcemap configuration. For example, if a vendor file is being processed - // and vendor sourcemaps are disabled, the `inputSourceMap` property will be `undefined` - // which will effectively disable linker sourcemapping for vendor files. - if (customOptions.angularLinker && configuration.options.inputSourceMap) { - customOptions.angularLinker.sourcemap = true; - } - return { ...configuration.options, // Workaround for https://github.com/babel/babel-loader/pull/896 is available From c0acf742128651f29eb9ddb9eb39bf11446705c0 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 6 Jul 2021 16:00:00 +0200 Subject: [PATCH 2/3] test(@angular-devkit/build-angular): validate that libraries source-maps are created --- .../library/library-consumption-ivy-full.ts | 33 +++++++++++------ .../library-consumption-ivy-partial.ts | 33 +++++++++++------ .../library/library-consumption-ve.ts | 35 +++++++++++++------ 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-full.ts b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-full.ts index b523bbc67bb1..27443966a96c 100644 --- a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-full.ts +++ b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-full.ts @@ -1,11 +1,21 @@ -import { writeFile } from '../../../utils/fs'; +import { expectFileToMatch, writeMultipleFiles } from '../../../utils/fs'; import { ng } from '../../../utils/process'; import { updateJsonFile } from '../../../utils/project'; export default async function () { await ng('generate', 'library', 'my-lib'); - await writeFile('./src/app/app.module.ts', ` + // Force an external template + await writeMultipleFiles({ + 'projects/my-lib/src/lib/my-lib.component.html': `

my-lib works!

`, + 'projects/my-lib/src/lib/my-lib.component.ts': `import { Component } from '@angular/core'; + + @Component({ + selector: 'lib-my-lib', + templateUrl: './my-lib.component.html', + }) + export class MyLibComponent {}`, + './src/app/app.module.ts': ` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { MyLibModule } from 'my-lib'; @@ -24,9 +34,8 @@ export default async function () { bootstrap: [AppComponent] }) export class AppModule { } - `); - - await writeFile('./src/app/app.component.ts', ` + `, + './src/app/app.component.ts': ` import { Component } from '@angular/core'; import { MyLibService } from 'my-lib'; @@ -41,9 +50,8 @@ export default async function () { console.log(myLibService); } } - `); - - await writeFile('e2e/src/app.e2e-spec.ts', ` + `, + 'e2e/src/app.e2e-spec.ts': ` import { browser, logging, element, by } from 'protractor'; import { AppPage } from './app.po'; @@ -67,7 +75,8 @@ export default async function () { })); }); }); - `); + `, + }); // Build library in full mode (development) await ng('build', 'my-lib', '--configuration=development'); @@ -76,7 +85,7 @@ export default async function () { await runTests(); // JIT linking - await updateJsonFile('angular.json', config => { + await updateJsonFile('angular.json', (config) => { const build = config.projects['test-project'].architect.build; build.options.aot = false; build.configurations.production.buildOptimizer = false; @@ -89,4 +98,8 @@ async function runTests(): Promise { // Check that the tests succeeds both with named project, unnamed (should test app), and prod. await ng('e2e'); await ng('e2e', 'test-project', '--devServerTarget=test-project:serve:production'); + + // Validate that sourcemaps for the library exists. + await ng('build', '--configuration=development'); + await expectFileToMatch('dist/test-project/main.js.map', 'projects/my-lib/src/public-api.ts'); } diff --git a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-partial.ts b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-partial.ts index 076ceb65cd80..4ca8f3fb3ad7 100644 --- a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-partial.ts +++ b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ivy-partial.ts @@ -1,11 +1,21 @@ -import { writeFile } from '../../../utils/fs'; +import { expectFileToMatch, writeMultipleFiles } from '../../../utils/fs'; import { ng } from '../../../utils/process'; import { updateJsonFile } from '../../../utils/project'; export default async function () { await ng('generate', 'library', 'my-lib'); - await writeFile('./src/app/app.module.ts', ` + // Force an external template + await writeMultipleFiles({ + 'projects/my-lib/src/lib/my-lib.component.html': `

my-lib works!

`, + 'projects/my-lib/src/lib/my-lib.component.ts': `import { Component } from '@angular/core'; + + @Component({ + selector: 'lib-my-lib', + templateUrl: './my-lib.component.html', + }) + export class MyLibComponent {}`, + './src/app/app.module.ts': ` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { MyLibModule } from 'my-lib'; @@ -24,9 +34,8 @@ export default async function () { bootstrap: [AppComponent] }) export class AppModule { } - `); - - await writeFile('./src/app/app.component.ts', ` + `, + './src/app/app.component.ts': ` import { Component } from '@angular/core'; import { MyLibService } from 'my-lib'; @@ -41,9 +50,8 @@ export default async function () { console.log(myLibService); } } - `); - - await writeFile('e2e/src/app.e2e-spec.ts', ` + `, + 'e2e/src/app.e2e-spec.ts': ` import { browser, logging, element, by } from 'protractor'; import { AppPage } from './app.po'; @@ -67,7 +75,8 @@ export default async function () { })); }); }); - `); + `, + }); // Build library in partial mode (production) await ng('build', 'my-lib', '--configuration=production'); @@ -76,7 +85,7 @@ export default async function () { await runTests(); // JIT linking - await updateJsonFile('angular.json', config => { + await updateJsonFile('angular.json', (config) => { const build = config.projects['test-project'].architect.build; build.options.aot = false; build.configurations.production.buildOptimizer = false; @@ -89,4 +98,8 @@ async function runTests(): Promise { // Check that the tests succeeds both with named project, unnamed (should test app), and prod. await ng('e2e'); await ng('e2e', 'test-project', '--devServerTarget=test-project:serve:production'); + + // Validate that sourcemaps for the library exists. + await ng('build', '--configuration=development'); + await expectFileToMatch('dist/test-project/main.js.map', 'projects/my-lib/src/public-api.ts'); } diff --git a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ve.ts b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ve.ts index 34c4114fdf8f..7341457faafa 100644 --- a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ve.ts +++ b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-ve.ts @@ -1,11 +1,11 @@ -import { writeFile } from '../../../utils/fs'; +import { expectFileToMatch, writeMultipleFiles } from '../../../utils/fs'; import { ng } from '../../../utils/process'; import { updateJsonFile } from '../../../utils/project'; export default async function () { await ng('generate', 'library', 'my-lib'); - await updateJsonFile('projects/my-lib/tsconfig.lib.prod.json', config => { + await updateJsonFile('projects/my-lib/tsconfig.lib.prod.json', (config) => { const { angularCompilerOptions = {} } = config; angularCompilerOptions.enableIvy = false; angularCompilerOptions.skipTemplateCodegen = true; @@ -13,7 +13,17 @@ export default async function () { config.angularCompilerOptions = angularCompilerOptions; }); - await writeFile('./src/app/app.module.ts', ` + // Force an external template + await writeMultipleFiles({ + 'projects/my-lib/src/lib/my-lib.component.html': `

my-lib works!

`, + 'projects/my-lib/src/lib/my-lib.component.ts': `import { Component } from '@angular/core'; + + @Component({ + selector: 'lib-my-lib', + templateUrl: './my-lib.component.html', + }) + export class MyLibComponent {}`, + './src/app/app.module.ts': ` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { MyLibModule } from 'my-lib'; @@ -32,9 +42,8 @@ export default async function () { bootstrap: [AppComponent] }) export class AppModule { } - `); - - await writeFile('./src/app/app.component.ts', ` + `, + './src/app/app.component.ts': ` import { Component } from '@angular/core'; import { MyLibService } from 'my-lib'; @@ -49,9 +58,8 @@ export default async function () { console.log(myLibService); } } - `); - - await writeFile('e2e/src/app.e2e-spec.ts', ` + `, + 'e2e/src/app.e2e-spec.ts': ` import { browser, logging, element, by } from 'protractor'; import { AppPage } from './app.po'; @@ -75,7 +83,8 @@ export default async function () { })); }); }); - `); + `, + }); // Build library in VE mode (production) await ng('build', 'my-lib', '--configuration=production'); @@ -84,7 +93,7 @@ export default async function () { await runTests(); // JIT linking - await updateJsonFile('angular.json', config => { + await updateJsonFile('angular.json', (config) => { const build = config.projects['test-project'].architect.build; build.options.aot = false; build.configurations.production.buildOptimizer = false; @@ -97,4 +106,8 @@ async function runTests(): Promise { // Check that the tests succeeds both with named project, unnamed (should test app), and prod. await ng('e2e'); await ng('e2e', 'test-project', '--devServerTarget=test-project:serve:production'); + + // Validate that sourcemaps for the library exists. + await ng('build', '--configuration=development'); + await expectFileToMatch('dist/test-project/main.js.map', 'projects/my-lib/src/public-api.ts'); } From 88737e39b91d4fe89342b98d81f72fb727a344cd Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 6 Jul 2021 16:11:15 +0200 Subject: [PATCH 3/3] fix(@angular-devkit/build-angular): force linker `sourceMapping` option to false. This is an interim solution until https://github.com/angular/angular/issues/42769 is fixed. Closes #21271 --- .../build_angular/src/babel/presets/application.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/angular_devkit/build_angular/src/babel/presets/application.ts b/packages/angular_devkit/build_angular/src/babel/presets/application.ts index 5a092f6d89a9..fcc6b3bdd79f 100644 --- a/packages/angular_devkit/build_angular/src/babel/presets/application.ts +++ b/packages/angular_devkit/build_angular/src/babel/presets/application.ts @@ -137,6 +137,8 @@ export default function (api: unknown, options: ApplicationPresetOptions) { plugins.push( createEs2015LinkerPlugin({ linkerJitMode: options.angularLinker.jitMode, + // This is a workaround until https://github.com/angular/angular/issues/42769 is fixed. + sourceMapping: false, logger: createNgtscLogger(options.diagnosticReporter), fileSystem: { resolve: path.resolve,