From 8925674870973ce58e4f5b911fd3768811248916 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Wed, 17 Feb 2021 10:59:57 -0500 Subject: [PATCH] fix(@angular-devkit/build-angular): improve fidelity and performance of babel loader sourcemaps This change uses the `@ampproject/remapping` package to merge sourcemaps generated from the customized babel loader used to perform the partial compilation linking in applications as well as other optimization and downleveling transformations. This provides more accurate output mappings as well as improved performance and lower memory usage when source maps are enabled within a build. (cherry picked from commit f10a8283367390031767eb67fcbea3ebbd5a3955) --- .../build_angular/src/babel/babel-loader.d.ts | 15 ++++++++--- .../build_angular/src/babel/webpack-loader.ts | 25 ++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/babel/babel-loader.d.ts b/packages/angular_devkit/build_angular/src/babel/babel-loader.d.ts index 0c0756d9e54a..49fbff8b8344 100644 --- a/packages/angular_devkit/build_angular/src/babel/babel-loader.d.ts +++ b/packages/angular_devkit/build_angular/src/babel/babel-loader.d.ts @@ -7,9 +7,7 @@ */ declare module 'babel-loader' { - type BabelLoaderCustomizer = ( - babel: typeof import('@babel/core'), - ) => { + type BabelLoaderCustomizer = (babel: typeof import('@babel/core')) => { customOptions?( this: import('webpack').loader.LoaderContext, loaderOptions: Record, @@ -20,6 +18,17 @@ declare module 'babel-loader' { configuration: import('@babel/core').PartialConfig, loaderArguments: { source: string; map?: unknown; customOptions: T }, ): import('@babel/core').TransformOptions; + result?( + this: import('webpack').loader.LoaderContext, + result: import('@babel/core').BabelFileResult, + context: { + source: string; + map?: unknown; + customOptions: T; + configuration: import('@babel/core').PartialConfig; + options: import('@babel/core').TransformOptions; + }, + ): import('@babel/core').BabelFileResult; }; function custom(customizer: BabelLoaderCustomizer): import('webpack').loader.Loader; } 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 ac102b6259cb..9250b0e8d117 100644 --- a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts +++ b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ +import remapping from '@ampproject/remapping'; import { needsLinking } from '@angular/compiler-cli/linker'; import { custom } from 'babel-loader'; import { ScriptTarget } from 'typescript'; @@ -21,6 +22,9 @@ interface AngularCustomOptions extends Pick[0], unknown[]>; + function requiresLinking(path: string, source: string): boolean { // @angular/core and @angular/compiler will cause false positives // Also, TypeScript files do not require linking @@ -146,10 +150,10 @@ export default custom(() => { return { ...configuration.options, - // Workaround for https://github.com/babel/babel-loader/pull/896 is available - // Delete once the above PR is released + // Using `false` disables babel from attempting to locate sourcemaps or process any inline maps. + // The babel types do not include the false option even though it is valid // eslint-disable-next-line @typescript-eslint/no-explicit-any - inputSourceMap: configuration.options.inputSourceMap || (false as any), // Typings are not correct + inputSourceMap: false as any, plugins, presets: [ ...(configuration.options.presets || []), @@ -174,5 +178,20 @@ export default custom(() => { ], }; }, + result(result, { map: inputSourceMap }) { + if (result.map && inputSourceMap) { + // Merge the intermediate sourcemap generated by babel with the input source map. + // The casting is required due to slight differences in the types for babel and + // `@ampproject/remapping` source map objects but both are compatible with Webpack. + // This method for merging is used because it provides more accurate output + // and is faster while using less memory. + result.map = remapping( + [result.map as SourceMapInput, inputSourceMap as SourceMapInput], + () => null, + ) as typeof result.map; + } + + return result; + }, }; });