Skip to content
This repository was archived by the owner on Sep 9, 2021. It is now read-only.

Commit 5047abb

Browse files
authoredJul 30, 2020
fix: source maps when inline using without fallback (#269)
1 parent f93804e commit 5047abb

9 files changed

+744
-494
lines changed
 

‎package-lock.json

+511-458
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -45,31 +45,31 @@
4545
"loader-utils": "^2.0.0"
4646
},
4747
"devDependencies": {
48-
"@babel/cli": "^7.10.4",
49-
"@babel/core": "^7.10.4",
48+
"@babel/cli": "^7.10.5",
49+
"@babel/core": "^7.10.5",
5050
"@babel/preset-env": "^7.10.4",
5151
"@commitlint/cli": "^9.1.1",
5252
"@commitlint/config-conventional": "^9.1.1",
5353
"@webpack-contrib/defaults": "^6.3.0",
5454
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
55-
"babel-jest": "^26.1.0",
55+
"babel-jest": "^26.2.0",
5656
"cross-env": "^7.0.2",
5757
"del": "^5.1.0",
5858
"del-cli": "^3.0.1",
59-
"eslint": "^7.4.0",
59+
"eslint": "^7.5.0",
6060
"eslint-config-prettier": "^6.11.0",
6161
"eslint-plugin-import": "^2.22.0",
6262
"express": "^4.17.1",
6363
"get-port": "^5.1.1",
6464
"html-webpack-plugin": "^4.3.0",
6565
"husky": "^4.2.5",
66-
"jest": "^26.1.0",
66+
"jest": "^26.2.1",
6767
"lint-staged": "^10.2.11",
6868
"memfs": "^3.2.0",
69-
"nanoid": "^3.1.10",
69+
"nanoid": "^3.1.12",
7070
"npm-run-all": "^4.1.5",
7171
"prettier": "^2.0.5",
72-
"puppeteer": "^5.1.0",
72+
"puppeteer": "^5.2.1",
7373
"standard-version": "^8.0.2",
7474
"webpack": "^4.44.0"
7575
},

‎src/supportWebpack4.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { getWorker } from './utils';
1+
import { getWorker, sourceMappingURLRegex } from './utils';
22

33
export default function runAsChild(worker, request, options, callback) {
4-
const subCache = `subcache ${__dirname} ${request}`;
4+
const subCache = `subcache worker-loader ${request}`;
55

66
// eslint-disable-next-line no-param-reassign
77
worker.compilation = (compilation) => {
@@ -16,25 +16,33 @@ export default function runAsChild(worker, request, options, callback) {
1616
}
1717
};
1818

19-
worker.compiler.hooks.compilation.tap('WorkerLoader', worker.compilation);
19+
worker.compiler.hooks.compilation.tap('worker-loader', worker.compilation);
2020
worker.compiler.runAsChild((error, entries, compilation) => {
2121
if (error) {
2222
return callback(error);
2323
}
2424

2525
if (entries[0]) {
2626
// eslint-disable-next-line no-param-reassign, prefer-destructuring
27-
worker.file = entries[0].files[0];
27+
worker.filename = entries[0].files[0];
28+
29+
let workerSource = compilation.assets[worker.filename].source();
30+
31+
if (options.inline === 'no-fallback') {
32+
// Remove `/* sourceMappingURL=url */` comment
33+
workerSource = workerSource.replace(sourceMappingURLRegex, '');
34+
}
2835

2936
// eslint-disable-next-line no-param-reassign
30-
worker.factory = getWorker(
31-
worker.file,
32-
compilation.assets[worker.file].source(),
33-
options
34-
);
37+
worker.factory = getWorker(worker.filename, workerSource, options);
3538

3639
if (options.inline === 'no-fallback') {
37-
delete this._compilation.assets[worker.file];
40+
delete this._compilation.assets[worker.filename];
41+
42+
// TODO improve this, we should store generated source maps files for file in `assetInfo`
43+
if (this._compilation.assets[`${worker.filename}.map`]) {
44+
delete this._compilation.assets[`${worker.filename}.map`];
45+
}
3846
}
3947

4048
const esModule =

‎src/supportWebpack5.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getWorker } from './utils';
1+
import { getWorker, sourceMappingURLRegex } from './utils';
22

33
export default function runAsChild(worker, options, callback) {
44
// eslint-disable-next-line import/no-unresolved, global-require
@@ -11,10 +11,10 @@ export default function runAsChild(worker, options, callback) {
1111

1212
if (entries[0]) {
1313
// eslint-disable-next-line no-param-reassign, prefer-destructuring
14-
worker.file = [...entries[0].files][0];
14+
worker.filename = [...entries[0].files][0];
1515

1616
const cacheIdent = `${worker.compiler.compilerPath}/worker-loader/${__dirname}/${this.resource}`;
17-
const cacheETag = getLazyHashedEtag(compilation.assets[worker.file]);
17+
const cacheETag = getLazyHashedEtag(compilation.assets[worker.filename]);
1818

1919
return worker.compiler.cache.get(
2020
cacheIdent,
@@ -25,19 +25,27 @@ export default function runAsChild(worker, options, callback) {
2525
}
2626

2727
if (options.inline === 'no-fallback') {
28-
delete this._compilation.assets[worker.file];
28+
delete this._compilation.assets[worker.filename];
29+
30+
// TODO improve this, we should store generated source maps files for file in `assetInfo`
31+
if (this._compilation.assets[`${worker.filename}.map`]) {
32+
delete this._compilation.assets[`${worker.filename}.map`];
33+
}
2934
}
3035

3136
if (content) {
3237
return callback(null, content);
3338
}
3439

40+
let workerSource = compilation.assets[worker.filename].source();
41+
42+
if (options.inline === 'no-fallback') {
43+
// Remove `/* sourceMappingURL=url */` comment
44+
workerSource = workerSource.replace(sourceMappingURLRegex, '');
45+
}
46+
3547
// eslint-disable-next-line no-param-reassign
36-
worker.factory = getWorker(
37-
worker.file,
38-
compilation.assets[worker.file].source(),
39-
options
40-
);
48+
worker.factory = getWorker(worker.filename, workerSource, options);
4149

4250
const esModule =
4351
typeof options.esModule !== 'undefined' ? options.esModule : true;

‎src/utils.js

+29-4
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function getExternalsType(compilerOptions) {
3232
return 'var';
3333
}
3434

35-
function getWorker(file, content, options) {
35+
function getWorker(workerFilename, workerSource, options) {
3636
let workerConstructor;
3737
let workerOptions;
3838

@@ -52,24 +52,49 @@ function getWorker(file, content, options) {
5252
let fallbackWorkerPath;
5353

5454
if (options.inline === 'fallback') {
55-
fallbackWorkerPath = `__webpack_public_path__ + ${JSON.stringify(file)}`;
55+
fallbackWorkerPath = `__webpack_public_path__ + ${JSON.stringify(
56+
workerFilename
57+
)}`;
5658
}
5759

5860
return `require(${InlineWorkerPath})(${JSON.stringify(
59-
content
61+
workerSource
6062
)}, ${JSON.stringify(workerConstructor)}, ${JSON.stringify(
6163
workerOptions
6264
)}, ${fallbackWorkerPath})`;
6365
}
6466

6567
return `new ${workerConstructor}(__webpack_public_path__ + ${JSON.stringify(
66-
file
68+
workerFilename
6769
)}${workerOptions ? `, ${JSON.stringify(workerOptions)}` : ''})`;
6870
}
6971

72+
// Matches only the last occurrence of sourceMappingURL
73+
const innerRegex = /\s*[#@]\s*sourceMappingURL\s*=\s*([^\s'"]*)\s*/;
74+
75+
/* eslint-disable prefer-template */
76+
const sourceMappingURLRegex = RegExp(
77+
'(?:' +
78+
'/\\*' +
79+
'(?:\\s*\r?\n(?://)?)?' +
80+
'(?:' +
81+
innerRegex.source +
82+
')' +
83+
'\\s*' +
84+
'\\*/' +
85+
'|' +
86+
'//(?:' +
87+
innerRegex.source +
88+
')' +
89+
')' +
90+
'\\s*'
91+
);
92+
/* eslint-enable prefer-template */
93+
7094
export {
7195
getDefaultFilename,
7296
getDefaultChunkFilename,
7397
getExternalsType,
7498
getWorker,
99+
sourceMappingURLRegex,
75100
};

‎test/__snapshots__/inline-option.test.js.snap

+21-3
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,32 @@ exports[`"inline" option should not work by default: result 1`] = `"{\\"postMess
1313

1414
exports[`"inline" option should not work by default: warnings 1`] = `Array []`;
1515

16-
exports[`"inline" option should not work with "no-fallback" value: errors 1`] = `Array []`;
16+
exports[`"inline" option should work with "fallback" value and the "devtool" option ("source-map" value): errors 1`] = `Array []`;
1717

18-
exports[`"inline" option should not work with "no-fallback" value: result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
18+
exports[`"inline" option should work with "fallback" value and the "devtool" option ("source-map" value): result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
1919

20-
exports[`"inline" option should not work with "no-fallback" value: warnings 1`] = `Array []`;
20+
exports[`"inline" option should work with "fallback" value and the "devtool" option ("source-map" value): warnings 1`] = `Array []`;
2121

2222
exports[`"inline" option should work with "fallback" value: errors 1`] = `Array []`;
2323

2424
exports[`"inline" option should work with "fallback" value: result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
2525

2626
exports[`"inline" option should work with "fallback" value: warnings 1`] = `Array []`;
27+
28+
exports[`"inline" option should work with "no-fallback" value and the "devtool" option ("source-map" value): errors 1`] = `Array []`;
29+
30+
exports[`"inline" option should work with "no-fallback" value and the "devtool" option ("source-map" value): errors 2`] = `Array []`;
31+
32+
exports[`"inline" option should work with "no-fallback" value and the "devtool" option ("source-map" value): result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
33+
34+
exports[`"inline" option should work with "no-fallback" value and the "devtool" option ("source-map" value): result 2`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
35+
36+
exports[`"inline" option should work with "no-fallback" value and the "devtool" option ("source-map" value): warnings 1`] = `Array []`;
37+
38+
exports[`"inline" option should work with "no-fallback" value and the "devtool" option ("source-map" value): warnings 2`] = `Array []`;
39+
40+
exports[`"inline" option should work with "no-fallback" value: errors 1`] = `Array []`;
41+
42+
exports[`"inline" option should work with "no-fallback" value: result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
43+
44+
exports[`"inline" option should work with "no-fallback" value: warnings 1`] = `Array []`;

‎test/__snapshots__/loader.test.js.snap

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`worker-loader should work and respect the "devtool" option ("false" value): errors 1`] = `Array []`;
4+
5+
exports[`worker-loader should work and respect the "devtool" option ("false" value): module 1`] = `
6+
"export default function() {
7+
return new Worker(__webpack_public_path__ + \\"test.worker.js\\");
8+
};
9+
"
10+
`;
11+
12+
exports[`worker-loader should work and respect the "devtool" option ("false" value): result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;
13+
14+
exports[`worker-loader should work and respect the "devtool" option ("false" value): warnings 1`] = `Array []`;
15+
316
exports[`worker-loader should work with "externals": errors 1`] = `Array []`;
417

518
exports[`worker-loader should work with "externals": module 1`] = `

‎test/inline-option.test.js

+95-3
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,121 @@ describe('"inline" option', () => {
2222
expect(getErrors(stats)).toMatchSnapshot('errors');
2323
});
2424

25-
it('should not work with "no-fallback" value', async () => {
25+
it('should work with "no-fallback" value', async () => {
2626
const compiler = getCompiler('./basic/entry.js', { inline: 'no-fallback' });
2727
const stats = await compile(compiler);
2828
const result = await getResultFromBrowser(stats);
2929
const moduleSource = getModuleSource('./basic/worker.js', stats);
3030

3131
expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
32-
expect(moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1).toBe(true);
32+
expect(
33+
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1
34+
).toBe(true);
3335
expect(stats.compilation.assets['test.worker.js']).toBeUndefined();
3436
expect(result).toMatchSnapshot('result');
3537
expect(getWarnings(stats)).toMatchSnapshot('warnings');
3638
expect(getErrors(stats)).toMatchSnapshot('errors');
3739
});
3840

41+
it('should work with "no-fallback" value and the "devtool" option ("source-map" value)', async () => {
42+
const compiler = getCompiler(
43+
'./basic/entry.js',
44+
{ inline: 'no-fallback' },
45+
{ devtool: 'source-map' }
46+
);
47+
const stats = await compile(compiler);
48+
const result = await getResultFromBrowser(stats);
49+
const moduleSource = getModuleSource('./basic/worker.js', stats);
50+
51+
expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
52+
expect(
53+
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1
54+
).toBe(true);
55+
expect(
56+
moduleSource.indexOf('sourceMappingURL=test.worker.js.map"') === -1
57+
).toBe(true);
58+
expect(stats.compilation.assets['test.worker.js']).toBeUndefined();
59+
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
60+
expect(result).toMatchSnapshot('result');
61+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
62+
expect(getErrors(stats)).toMatchSnapshot('errors');
63+
});
64+
65+
it('should work with "no-fallback" value and the "devtool" option ("source-map" value)', async () => {
66+
const compiler = getCompiler(
67+
'./basic/entry.js',
68+
{ inline: 'no-fallback' },
69+
{ devtool: false }
70+
);
71+
const stats = await compile(compiler);
72+
const result = await getResultFromBrowser(stats);
73+
const moduleSource = getModuleSource('./basic/worker.js', stats);
74+
75+
expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
76+
expect(
77+
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1
78+
).toBe(true);
79+
expect(stats.compilation.assets['test.worker.js']).toBeUndefined();
80+
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
81+
expect(result).toMatchSnapshot('result');
82+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
83+
expect(getErrors(stats)).toMatchSnapshot('errors');
84+
});
85+
3986
it('should work with "fallback" value', async () => {
4087
const compiler = getCompiler('./basic/entry.js', { inline: 'fallback' });
4188
const stats = await compile(compiler);
4289
const result = await getResultFromBrowser(stats);
4390
const moduleSource = getModuleSource('./basic/worker.js', stats);
4491

4592
expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
46-
expect(moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0).toBe(true);
93+
expect(
94+
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0
95+
).toBe(true);
96+
expect(stats.compilation.assets['test.worker.js']).toBeDefined();
97+
expect(result).toMatchSnapshot('result');
98+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
99+
expect(getErrors(stats)).toMatchSnapshot('errors');
100+
});
101+
102+
// TODO broken on webpack@5
103+
// it.skip('should work with "fallback" value and the "devtool" option ("source-map" value)', async () => {
104+
// const compiler = getCompiler(
105+
// './basic/entry.js',
106+
// { inline: 'fallback' },
107+
// { devtool: 'source-map' }
108+
// );
109+
// const stats = await compile(compiler);
110+
// const result = await getResultFromBrowser(stats);
111+
// const moduleSource = getModuleSource('./basic/worker.js', stats);
112+
//
113+
// expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
114+
// expect(
115+
// moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0
116+
// ).toBe(true);
117+
// expect(stats.compilation.assets['test.worker.js']).toBeDefined();
118+
// expect(stats.compilation.assets['test.worker.js.map']).toBeDefined();
119+
// expect(result).toMatchSnapshot('result');
120+
// expect(getWarnings(stats)).toMatchSnapshot('warnings');
121+
// expect(getErrors(stats)).toMatchSnapshot('errors');
122+
// });
123+
124+
it('should work with "fallback" value and the "devtool" option ("source-map" value)', async () => {
125+
const compiler = getCompiler(
126+
'./basic/entry.js',
127+
{ inline: 'fallback' },
128+
{ devtool: false }
129+
);
130+
const stats = await compile(compiler);
131+
const result = await getResultFromBrowser(stats);
132+
const moduleSource = getModuleSource('./basic/worker.js', stats);
133+
134+
expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
135+
expect(
136+
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0
137+
).toBe(true);
47138
expect(stats.compilation.assets['test.worker.js']).toBeDefined();
139+
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
48140
expect(result).toMatchSnapshot('result');
49141
expect(getWarnings(stats)).toMatchSnapshot('warnings');
50142
expect(getErrors(stats)).toMatchSnapshot('errors');

‎test/loader.test.js

+33
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,37 @@ describe('worker-loader', () => {
8080
expect(getWarnings(stats)).toMatchSnapshot('warnings');
8181
expect(getErrors(stats)).toMatchSnapshot('errors');
8282
});
83+
84+
// TODO broken on webpack@5
85+
// it.skip('should work and respect the "devtool" option ("source-map" value)', async () => {
86+
// const compiler = getCompiler(
87+
// './basic/entry.js',
88+
// {},
89+
// { devtool: 'source-map' }
90+
// );
91+
// const stats = await compile(compiler);
92+
// const result = await getResultFromBrowser(stats);
93+
//
94+
// expect(getModuleSource('./basic/worker.js', stats)).toMatchSnapshot(
95+
// 'module'
96+
// );
97+
// expect(stats.compilation.assets['test.worker.js.map']).toBeDefined();
98+
// expect(result).toMatchSnapshot('result');
99+
// expect(getWarnings(stats)).toMatchSnapshot('warnings');
100+
// expect(getErrors(stats)).toMatchSnapshot('errors');
101+
// });
102+
103+
it('should work and respect the "devtool" option ("false" value)', async () => {
104+
const compiler = getCompiler('./basic/entry.js', {}, { devtool: false });
105+
const stats = await compile(compiler);
106+
const result = await getResultFromBrowser(stats);
107+
108+
expect(getModuleSource('./basic/worker.js', stats)).toMatchSnapshot(
109+
'module'
110+
);
111+
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
112+
expect(result).toMatchSnapshot('result');
113+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
114+
expect(getErrors(stats)).toMatchSnapshot('errors');
115+
});
83116
});

0 commit comments

Comments
 (0)
This repository has been archived.