Skip to content

Commit fc7b18f

Browse files
committed
fix(@angular/build): allow disabling sourcemaps in the dev server
This change introduces the ability to disable sourcemaps when running the development server. A new Vite plugin has been added to remove sourcemap comments from generated assets. The dev server's configuration has been updated to conditionally apply this plugin and control CSS sourcemap generation based on the project's sourceMap setting. Closes #31331
1 parent ec7dd59 commit fc7b18f

File tree

5 files changed

+107
-27
lines changed

5 files changed

+107
-27
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import { executeDevServer } from '../../index';
10+
import { executeOnceAndFetch } from '../execute-fetch';
11+
import { describeServeBuilder } from '../jasmine-helpers';
12+
import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup';
13+
14+
describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => {
15+
describe('Behavior: "buildTarget sourceMap"', () => {
16+
beforeEach(async () => {
17+
// Application code is not needed for these tests
18+
await harness.writeFile('src/main.ts', 'console.log("foo");');
19+
});
20+
21+
it('should not include sourcemaps when disabled', async () => {
22+
setupTarget(harness, {
23+
sourceMap: false,
24+
});
25+
26+
harness.useTarget('serve', {
27+
...BASE_OPTIONS,
28+
});
29+
30+
const { result, response } = await executeOnceAndFetch(harness, '/main.js');
31+
expect(result?.success).toBeTrue();
32+
expect(await response?.text()).not.toContain('//# sourceMappingURL=');
33+
});
34+
35+
it('should include sourcemaps when enabled', async () => {
36+
setupTarget(harness, {
37+
sourceMap: true,
38+
});
39+
40+
harness.useTarget('serve', {
41+
...BASE_OPTIONS,
42+
});
43+
44+
const { result, response } = await executeOnceAndFetch(harness, '/main.js');
45+
expect(result?.success).toBeTrue();
46+
expect(await response?.text()).toContain('//# sourceMappingURL=');
47+
});
48+
});
49+
});

packages/angular/build/src/builders/dev-server/vite/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,11 @@ export async function* serveWithVite(
130130
browserOptions.forceI18nFlatOutput = true;
131131
}
132132

133-
const { vendor: thirdPartySourcemaps, scripts: scriptsSourcemaps } = normalizeSourceMaps(
134-
browserOptions.sourceMap ?? false,
135-
);
133+
const {
134+
vendor: thirdPartySourcemaps,
135+
scripts: scriptsSourcemaps,
136+
styles: stylesSourceMap,
137+
} = normalizeSourceMaps(browserOptions.sourceMap ?? false);
136138

137139
if (scriptsSourcemaps && browserOptions.server) {
138140
// https://nodejs.org/api/process.html#processsetsourcemapsenabledval
@@ -441,6 +443,7 @@ export async function* serveWithVite(
441443
},
442444
extensions?.middleware,
443445
transformers?.indexHtml,
446+
scriptsSourcemaps || stylesSourceMap,
444447
thirdPartySourcemaps,
445448
);
446449

packages/angular/build/src/builders/dev-server/vite/server.ts

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88

99
import { readFile } from 'node:fs/promises';
1010
import { join } from 'node:path';
11-
import type { Connect, InlineConfig, SSROptions, ServerOptions } from 'vite';
11+
import type { Connect, InlineConfig, Plugin, SSROptions, ServerOptions } from 'vite';
1212
import type { ComponentStyleRecord } from '../../../tools/vite/middlewares';
1313
import {
1414
ServerSsrMode,
1515
createAngularMemoryPlugin,
1616
createAngularSetupMiddlewaresPlugin,
1717
createAngularSsrTransformPlugin,
1818
createRemoveIdPrefixPlugin,
19+
removeSourceMapsPlugin,
1920
} from '../../../tools/vite/plugins';
2021
import { EsbuildLoaderOption, getDepOptimizationConfig } from '../../../tools/vite/utils';
2122
import { loadProxyConfiguration } from '../../../utils';
@@ -150,6 +151,7 @@ export async function setupServer(
150151
define: ApplicationBuilderInternalOptions['define'],
151152
extensionMiddleware?: Connect.NextHandleFunction[],
152153
indexHtmlTransformer?: (content: string) => Promise<string>,
154+
sourceMaps = true,
153155
thirdPartySourcemaps = false,
154156
): Promise<InlineConfig> {
155157
// dynamically import Vite for ESM compatibility
@@ -171,6 +173,33 @@ export async function setupServer(
171173
externalMetadata.explicitBrowser.length === 0 && ssrMode === ServerSsrMode.NoSsr;
172174
const cacheDir = join(serverOptions.cacheOptions.path, serverOptions.buildTarget.project, 'vite');
173175

176+
const plugins: Plugin[] = [
177+
createAngularSetupMiddlewaresPlugin({
178+
outputFiles,
179+
assets,
180+
indexHtmlTransformer,
181+
extensionMiddleware,
182+
componentStyles,
183+
templateUpdates,
184+
ssrMode,
185+
resetComponentUpdates: () => templateUpdates.clear(),
186+
projectRoot: serverOptions.projectRoot,
187+
}),
188+
createRemoveIdPrefixPlugin(externalMetadata.explicitBrowser),
189+
await createAngularSsrTransformPlugin(serverOptions.workspaceRoot),
190+
await createAngularMemoryPlugin({
191+
virtualProjectRoot,
192+
outputFiles,
193+
templateUpdates,
194+
external: externalMetadata.explicitBrowser,
195+
disableViteTransport: !serverOptions.liveReload,
196+
}),
197+
];
198+
199+
if (!sourceMaps) {
200+
plugins.push(removeSourceMapsPlugin);
201+
}
202+
174203
const configuration: InlineConfig = {
175204
configFile: false,
176205
envFile: false,
@@ -182,7 +211,7 @@ export async function setupServer(
182211
// We use custom as we do not rely on Vite's htmlFallbackMiddleware and indexHtmlMiddleware.
183212
appType: 'custom',
184213
css: {
185-
devSourcemap: true,
214+
devSourcemap: sourceMaps,
186215
},
187216
// Ensure custom 'file' loader build option entries are handled by Vite in application code that
188217
// reference third-party libraries. Relative usage is handled directly by the build and not Vite.
@@ -219,28 +248,7 @@ export async function setupServer(
219248
thirdPartySourcemaps,
220249
define,
221250
),
222-
plugins: [
223-
createAngularSetupMiddlewaresPlugin({
224-
outputFiles,
225-
assets,
226-
indexHtmlTransformer,
227-
extensionMiddleware,
228-
componentStyles,
229-
templateUpdates,
230-
ssrMode,
231-
resetComponentUpdates: () => templateUpdates.clear(),
232-
projectRoot: serverOptions.projectRoot,
233-
}),
234-
createRemoveIdPrefixPlugin(externalMetadata.explicitBrowser),
235-
await createAngularSsrTransformPlugin(serverOptions.workspaceRoot),
236-
await createAngularMemoryPlugin({
237-
virtualProjectRoot,
238-
outputFiles,
239-
templateUpdates,
240-
external: externalMetadata.explicitBrowser,
241-
disableViteTransport: !serverOptions.liveReload,
242-
}),
243-
],
251+
plugins,
244252
// Browser only optimizeDeps. (This does not run for SSR dependencies).
245253
optimizeDeps: getDepOptimizationConfig({
246254
// Only enable with caching since it causes prebundle dependencies to be cached

packages/angular/build/src/tools/vite/plugins/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export { createAngularMemoryPlugin } from './angular-memory-plugin';
1010
export { createRemoveIdPrefixPlugin } from './id-prefix-plugin';
1111
export { createAngularSetupMiddlewaresPlugin, ServerSsrMode } from './setup-middlewares-plugin';
1212
export { createAngularSsrTransformPlugin } from './ssr-transform-plugin';
13+
export { removeSourceMapsPlugin } from './remove-sourcemaps';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import type { Plugin } from 'vite';
10+
11+
export const removeSourceMapsPlugin: Plugin = {
12+
name: 'vite:angular-remove-sourcemaps',
13+
transform(code) {
14+
return {
15+
code,
16+
map: { mappings: '' },
17+
};
18+
},
19+
};

0 commit comments

Comments
 (0)