Skip to content

Commit 915032b

Browse files
committed
feat(@angular-devkit/build-angular): emit external sourcemaps for component styles
This commits, changes the behaviour in the esbuild based builders by emitting component sourcemaps in external files instead of inlining them. Closes angular#24049 and closes angular#26676
1 parent a708dcc commit 915032b

File tree

5 files changed

+100
-53
lines changed

5 files changed

+100
-53
lines changed

packages/angular_devkit/build_angular/src/builders/application/tests/options/sourcemap_spec.ts

+36
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,41 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
136136

137137
harness.expectFile('dist/browser/main.js.map').content.toContain('"x_google_ignoreList"');
138138
});
139+
140+
it('should generate component sourcemaps when sourcemaps when true', async () => {
141+
await harness.writeFile('src/app/app.component.css', `* { color: red}`);
142+
143+
harness.useTarget('build', {
144+
...BASE_OPTIONS,
145+
sourceMap: true,
146+
});
147+
148+
const { result } = await harness.executeOnce();
149+
150+
expect(result?.success).toBeTrue();
151+
152+
harness
153+
.expectFile('dist/browser/main.js')
154+
.content.toContain('sourceMappingURL=app.component.css.map');
155+
harness.expectFile('dist/browser/app.component.css.map').toExist();
156+
});
157+
158+
it('should not generate component sourcemaps when sourcemaps when true', async () => {
159+
await harness.writeFile('src/app/app.component.css', `* { color: red}`);
160+
161+
harness.useTarget('build', {
162+
...BASE_OPTIONS,
163+
sourceMap: false,
164+
});
165+
166+
const { result } = await harness.executeOnce();
167+
168+
expect(result?.success).toBeTrue();
169+
170+
harness
171+
.expectFile('dist/browser/main.js')
172+
.content.not.toContain('sourceMappingURL=app.component.css.map');
173+
harness.expectFile('dist/browser/app.component.css.map').toNotExist();
174+
});
139175
});
140176
});

packages/angular_devkit/build_angular/src/tools/esbuild/angular/compiler-plugin.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,15 @@ export function createCompilerPlugin(
164164
);
165165
}
166166

167-
const { contents, resourceFiles, referencedFiles, errors, warnings } = stylesheetResult;
167+
const { contents, outputFiles, metafile, referencedFiles, errors, warnings } =
168+
stylesheetResult;
168169
if (errors) {
169170
(result.errors ??= []).push(...errors);
170171
}
171172
(result.warnings ??= []).push(...warnings);
172173
additionalResults.set(stylesheetFile ?? containingFile, {
173-
outputFiles: resourceFiles,
174-
metafile: stylesheetResult.metafile,
174+
outputFiles,
175+
metafile,
175176
});
176177

177178
if (referencedFiles) {
@@ -420,7 +421,16 @@ export function createCompilerPlugin(
420421
for (const { outputFiles, metafile } of additionalResults.values()) {
421422
// Add any additional output files to the main output files
422423
if (outputFiles?.length) {
423-
result.outputFiles?.push(...outputFiles);
424+
const outdir = build.initialOptions.outdir;
425+
result.outputFiles?.push(
426+
...outputFiles.map((output) => {
427+
if (outdir) {
428+
// output.path = path.join(outdir, output.path);
429+
}
430+
431+
return output;
432+
}),
433+
);
424434
}
425435

426436
// Combine additional metafiles with main metafile

packages/angular_devkit/build_angular/src/tools/esbuild/angular/component-stylesheets.ts

+47-46
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ export class ComponentStylesheetBundler {
4545
constructor(
4646
private readonly options: BundleStylesheetOptions,
4747
private readonly incremental: boolean,
48-
) {}
48+
) {
49+
this.options.sourcemap = this.options.sourcemap ? 'linked' : false;
50+
}
4951

5052
async bundleFile(entry: string) {
5153
const bundlerContext = this.#fileContexts.getOrCreate(entry, () => {
@@ -57,7 +59,7 @@ export class ComponentStylesheetBundler {
5759
});
5860
});
5961

60-
return extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
62+
return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
6163
}
6264

6365
async bundleInline(data: string, filename: string, language: string) {
@@ -103,7 +105,7 @@ export class ComponentStylesheetBundler {
103105
});
104106

105107
// Extract the result of the bundling from the output files
106-
return extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
108+
return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
107109
}
108110

109111
invalidate(files: Iterable<string>) {
@@ -128,52 +130,51 @@ export class ComponentStylesheetBundler {
128130

129131
await Promise.allSettled(contexts.map((context) => context.dispose()));
130132
}
131-
}
132133

133-
function extractResult(result: BundleContextResult, referencedFiles?: Set<string>) {
134-
let contents = '';
135-
let map;
136-
let outputPath;
137-
const resourceFiles: OutputFile[] = [];
138-
if (!result.errors) {
139-
for (const outputFile of result.outputFiles) {
140-
const filename = path.basename(outputFile.path);
141-
if (outputFile.type === BuildOutputFileType.Media) {
142-
// The output files could also contain resources (images/fonts/etc.) that were referenced
143-
resourceFiles.push(outputFile);
144-
} else if (filename.endsWith('.css')) {
145-
outputPath = outputFile.path;
146-
contents = outputFile.text;
147-
} else if (filename.endsWith('.css.map')) {
148-
map = outputFile.text;
149-
} else {
150-
throw new Error(
151-
`Unexpected non CSS/Media file "${filename}" outputted during component stylesheet processing.`,
152-
);
134+
private extractResult(result: BundleContextResult, referencedFiles?: Set<string>) {
135+
let contents = '';
136+
const outputFiles: OutputFile[] = [];
137+
if (!result.errors) {
138+
for (const outputFile of result.outputFiles) {
139+
const filename = path.basename(outputFile.path);
140+
141+
// Needed for Bazel as otherwise the files will not be written in the correct place.
142+
outputFile.path = path.join(this.options.workspaceRoot, outputFile.path);
143+
144+
if (outputFile.type === BuildOutputFileType.Media) {
145+
// The output files could also contain resources (images/fonts/etc.) that were referenced
146+
outputFiles.push(outputFile);
147+
} else if (filename.endsWith('.css')) {
148+
contents = outputFile.text;
149+
} else if (filename.endsWith('.css.map')) {
150+
outputFiles.push(outputFile);
151+
} else {
152+
throw new Error(
153+
`Unexpected non CSS/Media file "${filename}" outputted during component stylesheet processing.`,
154+
);
155+
}
153156
}
154157
}
155-
}
156158

157-
let metafile;
158-
if (!result.errors) {
159-
metafile = result.metafile;
160-
// Remove entryPoint fields from outputs to prevent the internal component styles from being
161-
// treated as initial files. Also mark the entry as a component resource for stat reporting.
162-
Object.values(metafile.outputs).forEach((output) => {
163-
delete output.entryPoint;
164-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
165-
(output as any)['ng-component'] = true;
166-
});
167-
}
159+
let metafile;
160+
if (!result.errors) {
161+
metafile = result.metafile;
162+
// Remove entryPoint fields from outputs to prevent the internal component styles from being
163+
// treated as initial files. Also mark the entry as a component resource for stat reporting.
164+
Object.values(metafile.outputs).forEach((output) => {
165+
delete output.entryPoint;
166+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
167+
(output as any)['ng-component'] = true;
168+
});
169+
}
168170

169-
return {
170-
errors: result.errors,
171-
warnings: result.warnings,
172-
contents,
173-
map,
174-
path: outputPath,
175-
resourceFiles,
176-
metafile,
177-
referencedFiles,
178-
};
171+
return {
172+
errors: result.errors,
173+
warnings: result.warnings,
174+
contents,
175+
outputFiles,
176+
metafile,
177+
referencedFiles,
178+
};
179+
}
179180
}

packages/angular_devkit/build_angular/src/tools/esbuild/angular/jit-plugin-callbacks.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ export function setupJitPluginCallbacks(
121121
);
122122
}
123123

124-
const { contents, resourceFiles, errors, warnings, metafile, referencedFiles } =
124+
const { contents, outputFiles, errors, warnings, metafile, referencedFiles } =
125125
stylesheetResult;
126126

127-
additionalResultFiles.set(entry.path, { outputFiles: resourceFiles, metafile });
127+
additionalResultFiles.set(entry.path, { outputFiles, metafile });
128128

129129
return {
130130
errors,

packages/angular_devkit/build_angular/src/tools/esbuild/stylesheets/bundle-options.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface BundleStylesheetOptions {
2222
optimization: boolean;
2323
inlineFonts: boolean;
2424
preserveSymlinks?: boolean;
25-
sourcemap: boolean | 'external' | 'inline';
25+
sourcemap: boolean | 'external' | 'inline' | 'linked';
2626
outputNames: { bundles: string; media: string };
2727
includePaths?: string[];
2828
externalDependencies?: string[];

0 commit comments

Comments
 (0)