+146
-1
lines changedFilter options
+146
-1
lines changed Original file line number Diff line number Diff line change
@@ -10,6 +10,10 @@ import { Architect } from '@angular-devkit/architect';
10
10
import * as path from 'path';
11
11
import { browserBuild, createArchitect, host } from '../../../testing/test-utils';
12
12
13
+
// Following the naming conventions from
14
+
// https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm
15
+
const IGNORE_LIST = 'x_google_ignoreList';
16
+
13
17
describe('Browser Builder external source map', () => {
14
18
const target = { project: 'app', target: 'build' };
15
19
let architect: Architect;
@@ -50,3 +54,70 @@ describe('Browser Builder external source map', () => {
50
54
expect(hasTsSourcePaths).toBe(false, `vendor.js.map not should have '.ts' extentions`);
51
55
});
52
56
});
57
+
58
+
describe('Identifying third-party code in source maps', () => {
59
+
interface SourceMap {
60
+
sources: string[];
61
+
[IGNORE_LIST]: number[];
62
+
}
63
+
64
+
const target = { project: 'app', target: 'build' };
65
+
let architect: Architect;
66
+
67
+
beforeEach(async () => {
68
+
await host.initialize().toPromise();
69
+
architect = (await createArchitect(host.root())).architect;
70
+
});
71
+
afterEach(async () => host.restore().toPromise());
72
+
73
+
it('specifies which sources are third party when vendor processing is disabled', async () => {
74
+
const overrides = {
75
+
sourceMap: {
76
+
scripts: true,
77
+
vendor: false,
78
+
},
79
+
};
80
+
81
+
const { files } = await browserBuild(architect, host, target, overrides);
82
+
const mainMap: SourceMap = JSON.parse(await files['main.js.map']);
83
+
const polyfillsMap: SourceMap = JSON.parse(await files['polyfills.js.map']);
84
+
const runtimeMap: SourceMap = JSON.parse(await files['runtime.js.map']);
85
+
const vendorMap: SourceMap = JSON.parse(await files['vendor.js.map']);
86
+
87
+
expect(mainMap[IGNORE_LIST]).not.toBeUndefined();
88
+
expect(polyfillsMap[IGNORE_LIST]).not.toBeUndefined();
89
+
expect(runtimeMap[IGNORE_LIST]).not.toBeUndefined();
90
+
expect(vendorMap[IGNORE_LIST]).not.toBeUndefined();
91
+
92
+
expect(mainMap[IGNORE_LIST].length).toEqual(0);
93
+
expect(polyfillsMap[IGNORE_LIST].length).not.toEqual(0);
94
+
expect(runtimeMap[IGNORE_LIST].length).not.toEqual(0);
95
+
expect(vendorMap[IGNORE_LIST].length).not.toEqual(0);
96
+
97
+
const thirdPartyInMain = mainMap.sources.some((s) => s.includes('node_modules'));
98
+
const thirdPartyInPolyfills = polyfillsMap.sources.some((s) => s.includes('node_modules'));
99
+
const thirdPartyInRuntime = runtimeMap.sources.some((s) => s.includes('webpack'));
100
+
const thirdPartyInVendor = vendorMap.sources.some((s) => s.includes('node_modules'));
101
+
expect(thirdPartyInMain).toBe(false, `main.js.map should not include any node modules`);
102
+
expect(thirdPartyInPolyfills).toBe(true, `polyfills.js.map should include some node modules`);
103
+
expect(thirdPartyInRuntime).toBe(true, `runtime.js.map should include some webpack code`);
104
+
expect(thirdPartyInVendor).toBe(true, `vendor.js.map should include some node modules`);
105
+
106
+
// All sources in the main map are first-party.
107
+
expect(mainMap.sources.filter((_, i) => !mainMap[IGNORE_LIST].includes(i))).toEqual([
108
+
'./src/app/app.component.ts',
109
+
'./src/app/app.module.ts',
110
+
'./src/environments/environment.ts',
111
+
'./src/main.ts',
112
+
]);
113
+
114
+
// Only some sources in the polyfills map are first-party.
115
+
expect(polyfillsMap.sources.filter((_, i) => !polyfillsMap[IGNORE_LIST].includes(i))).toEqual([
116
+
'./src/polyfills.ts',
117
+
]);
118
+
119
+
// None of the sources in the runtime and vendor maps are first-party.
120
+
expect(runtimeMap.sources.filter((_, i) => !runtimeMap[IGNORE_LIST].includes(i))).toEqual([]);
121
+
expect(vendorMap.sources.filter((_, i) => !vendorMap[IGNORE_LIST].includes(i))).toEqual([]);
122
+
});
123
+
});
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ import {
29
29
JsonStatsPlugin,
30
30
ScriptsWebpackPlugin,
31
31
} from '../plugins';
32
+
import { DevToolsIgnorePlugin } from '../plugins/devtools-ignore-plugin';
32
33
import { NamedChunksPlugin } from '../plugins/named-chunks-plugin';
33
34
import { ProgressPlugin } from '../plugins/progress-plugin';
34
35
import { TransferSizePlugin } from '../plugins/transfer-size-plugin';
@@ -45,6 +46,8 @@ import {
45
46
globalScriptsByBundleName,
46
47
} from '../utils/helpers';
47
48
49
+
const VENDORS_TEST = /[\\/]node_modules[\\/]/;
50
+
48
51
// eslint-disable-next-line max-lines-per-function
49
52
export async function getCommonConfig(wco: WebpackConfigOptions): Promise<Configuration> {
50
53
const {
@@ -190,6 +193,8 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise<Config
190
193
include.push(/css$/);
191
194
}
192
195
196
+
extraPlugins.push(new DevToolsIgnorePlugin());
197
+
193
198
extraPlugins.push(
194
199
new SourceMapDevToolPlugin({
195
200
filename: '[file].map',
@@ -434,7 +439,7 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise<Config
434
439
name: 'vendor',
435
440
chunks: (chunk) => chunk.name === 'main',
436
441
enforce: true,
437
-
test: /[\\/]node_modules[\\/]/,
442
+
test: VENDORS_TEST,
438
443
},
439
444
},
440
445
},
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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.io/license
7
+
*/
8
+
9
+
import { Compilation, Compiler } from 'webpack';
10
+
11
+
// Following the naming conventions from
12
+
// https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm
13
+
const IGNORE_LIST = 'x_google_ignoreList';
14
+
15
+
const PLUGIN_NAME = 'devtools-ignore-plugin';
16
+
17
+
interface SourceMap {
18
+
sources: string[];
19
+
[IGNORE_LIST]: number[];
20
+
}
21
+
22
+
/**
23
+
* This plugin adds a field to source maps that identifies which sources are
24
+
* vendored or runtime-injected (aka third-party) sources. These are consumed by
25
+
* Chrome DevTools to automatically ignore-list sources.
26
+
*/
27
+
export class DevToolsIgnorePlugin {
28
+
apply(compiler: Compiler) {
29
+
const { RawSource } = compiler.webpack.sources;
30
+
31
+
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
32
+
compilation.hooks.processAssets.tap(
33
+
{
34
+
name: PLUGIN_NAME,
35
+
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
36
+
additionalAssets: true,
37
+
},
38
+
(assets) => {
39
+
for (const [name, asset] of Object.entries(assets)) {
40
+
// Instead of using `asset.map()` to fetch the source maps from
41
+
// SourceMapSource assets, process them directly as a RawSource.
42
+
// This is because `.map()` is slow and can take several seconds.
43
+
if (!name.endsWith('.map')) {
44
+
// Ignore non source map files.
45
+
continue;
46
+
}
47
+
48
+
const mapContent = asset.source().toString();
49
+
if (!mapContent) {
50
+
continue;
51
+
}
52
+
53
+
const map = JSON.parse(mapContent) as SourceMap;
54
+
const ignoreList = [];
55
+
56
+
for (const [index, path] of map.sources.entries()) {
57
+
if (path.includes('/node_modules/') || path.startsWith('webpack/')) {
58
+
ignoreList.push(index);
59
+
}
60
+
}
61
+
62
+
map[IGNORE_LIST] = ignoreList;
63
+
compilation.updateAsset(name, new RawSource(JSON.stringify(map)));
64
+
}
65
+
},
66
+
);
67
+
});
68
+
}
69
+
}
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4