Skip to content

Commit c1de633

Browse files
clydinalan-agius4
authored andcommitted
feat(@angular/build): allow control of source map sources content for application builds
The `sourceMap` option now contains an additional sub-option named `sourcesContent` that allows the exclusion of original file content from generated source maps. This option affects both JavaScript and stylesheet source maps. The value of the `sourcesContent` option defaults to `true`. Example usage to disable sources content: ``` "sourceMap": { "scripts": true, "styles": true, "sourcesContent": false } ```
1 parent 80a778a commit c1de633

File tree

7 files changed

+88
-0
lines changed

7 files changed

+88
-0
lines changed

packages/angular/build/src/builders/application/schema.json

+5
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@
370370
"type": "boolean",
371371
"description": "Resolve vendor packages source maps.",
372372
"default": false
373+
},
374+
"sourcesContent": {
375+
"type": "boolean",
376+
"description": "Output original source content for files within the source map.",
377+
"default": true
373378
}
374379
},
375380
"additionalProperties": false

packages/angular/build/src/builders/application/setup-bundling.ts

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ export function createComponentStyleBundler(
177177
// the same as being disabled. Disabling has the advantage of avoiding the overhead
178178
// of sourcemap processing.
179179
sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false,
180+
sourcesContent: sourcemapOptions.sourcesContent,
180181
outputNames,
181182
includePaths: stylePreprocessorOptions?.includePaths,
182183
// string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'.

packages/angular/build/src/builders/application/tests/options/sourcemap_spec.ts

+76
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,82 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
209209
harness.expectFile('dist/browser/main.js.map').content.toContain('"x_google_ignoreList"');
210210
});
211211

212+
it(`should not include 'sourcesContent' field when 'sourcesContent' suboption is false`, async () => {
213+
await harness.writeFile('src/styles.css', `div { flex: 1 }`);
214+
215+
harness.useTarget('build', {
216+
...BASE_OPTIONS,
217+
styles: ['src/styles.css'],
218+
sourceMap: { scripts: true, styles: true, sourcesContent: false },
219+
});
220+
221+
const { result } = await harness.executeOnce();
222+
223+
expect(result?.success).toBeTrue();
224+
225+
harness.expectFile('dist/browser/main.js.map').content.not.toContain('"sourcesContent"');
226+
227+
harness.expectFile('dist/browser/styles.css.map').toExist();
228+
harness.expectFile('dist/browser/styles.css.map').content.not.toContain('"sourcesContent"');
229+
});
230+
231+
it(`should include 'sourcesContent' field when 'sourcesContent' suboption is true`, async () => {
232+
await harness.writeFile('src/styles.css', `div { flex: 1 }`);
233+
234+
harness.useTarget('build', {
235+
...BASE_OPTIONS,
236+
styles: ['src/styles.css'],
237+
sourceMap: { scripts: true, styles: true, sourcesContent: true },
238+
});
239+
240+
const { result } = await harness.executeOnce();
241+
242+
expect(result?.success).toBeTrue();
243+
244+
harness.expectFile('dist/browser/main.js.map').content.toContain('"sourcesContent"');
245+
246+
harness.expectFile('dist/browser/styles.css.map').toExist();
247+
harness.expectFile('dist/browser/styles.css.map').content.toContain('"sourcesContent"');
248+
});
249+
250+
it(`should include 'sourcesContent' field when 'sourcesContent' suboption is not present`, async () => {
251+
await harness.writeFile('src/styles.css', `div { flex: 1 }`);
252+
253+
harness.useTarget('build', {
254+
...BASE_OPTIONS,
255+
styles: ['src/styles.css'],
256+
sourceMap: { scripts: true, styles: true },
257+
});
258+
259+
const { result } = await harness.executeOnce();
260+
261+
expect(result?.success).toBeTrue();
262+
263+
harness.expectFile('dist/browser/main.js.map').content.toContain('"sourcesContent"');
264+
265+
harness.expectFile('dist/browser/styles.css.map').toExist();
266+
harness.expectFile('dist/browser/styles.css.map').content.toContain('"sourcesContent"');
267+
});
268+
269+
it(`should include 'sourcesContent' field when 'sourceMap' is true`, async () => {
270+
await harness.writeFile('src/styles.css', `div { flex: 1 }`);
271+
272+
harness.useTarget('build', {
273+
...BASE_OPTIONS,
274+
styles: ['src/styles.css'],
275+
sourceMap: true,
276+
});
277+
278+
const { result } = await harness.executeOnce();
279+
280+
expect(result?.success).toBeTrue();
281+
282+
harness.expectFile('dist/browser/main.js.map').content.toContain('"sourcesContent"');
283+
284+
harness.expectFile('dist/browser/styles.css.map').toExist();
285+
harness.expectFile('dist/browser/styles.css.map').content.toContain('"sourcesContent"');
286+
});
287+
212288
it('should generate component sourcemaps when sourcemaps when true', async () => {
213289
await harness.writeFile('src/app/app.component.css', `* { color: red}`);
214290

packages/angular/build/src/tools/esbuild/application-code-bundle.ts

+1
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu
586586
outdir: workspaceRoot,
587587
outExtension: outExtension ? { '.js': `.${outExtension}` } : undefined,
588588
sourcemap: sourcemapOptions.scripts && (sourcemapOptions.hidden ? 'external' : true),
589+
sourcesContent: sourcemapOptions.sourcesContent,
589590
splitting: true,
590591
chunkNames: options.namedChunks ? '[name]-[hash]' : 'chunk-[hash]',
591592
tsconfig,

packages/angular/build/src/tools/esbuild/global-styles.ts

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export function createGlobalStylesBundleOptions(
5353
optimization: !!optimizationOptions.styles.minify,
5454
inlineFonts: !!optimizationOptions.fonts.inline,
5555
sourcemap: !!sourcemapOptions.styles && (sourcemapOptions.hidden ? 'external' : true),
56+
sourcesContent: sourcemapOptions.sourcesContent,
5657
preserveSymlinks,
5758
target,
5859
externalDependencies,

packages/angular/build/src/tools/esbuild/stylesheets/bundle-options.ts

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface BundleStylesheetOptions {
2424
inlineFonts: boolean;
2525
preserveSymlinks?: boolean;
2626
sourcemap: boolean | 'external' | 'inline' | 'linked';
27+
sourcesContent?: boolean;
2728
outputNames: { bundles: string; media: string };
2829
includePaths?: string[];
2930
sass?: StylesheetPluginsass;
@@ -77,6 +78,7 @@ export function createStylesheetBundleOptions(
7778
minify: options.optimization,
7879
metafile: true,
7980
sourcemap: options.sourcemap,
81+
sourcesContent: options.sourcesContent,
8082
outdir: options.workspaceRoot,
8183
write: false,
8284
platform: 'browser',

packages/angular/build/src/utils/normalize-source-maps.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ export function normalizeSourceMaps(sourceMap: SourceMapUnion): SourceMapClass {
1313
const styles = typeof sourceMap === 'object' ? sourceMap.styles : sourceMap;
1414
const hidden = (typeof sourceMap === 'object' && sourceMap.hidden) || false;
1515
const vendor = (typeof sourceMap === 'object' && sourceMap.vendor) || false;
16+
const sourcesContent = typeof sourceMap === 'object' ? sourceMap.sourcesContent : sourceMap;
1617

1718
return {
1819
vendor,
1920
hidden,
2021
scripts,
2122
styles,
23+
sourcesContent,
2224
};
2325
}

0 commit comments

Comments
 (0)