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

Commit

Permalink
fix: source maps when inline using without fallback (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi authored Jul 30, 2020
1 parent f93804e commit 5047abb
Show file tree
Hide file tree
Showing 9 changed files with 744 additions and 494 deletions.
969 changes: 511 additions & 458 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,31 @@
"loader-utils": "^2.0.0"
},
"devDependencies": {
"@babel/cli": "^7.10.4",
"@babel/core": "^7.10.4",
"@babel/cli": "^7.10.5",
"@babel/core": "^7.10.5",
"@babel/preset-env": "^7.10.4",
"@commitlint/cli": "^9.1.1",
"@commitlint/config-conventional": "^9.1.1",
"@webpack-contrib/defaults": "^6.3.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^26.1.0",
"babel-jest": "^26.2.0",
"cross-env": "^7.0.2",
"del": "^5.1.0",
"del-cli": "^3.0.1",
"eslint": "^7.4.0",
"eslint": "^7.5.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"express": "^4.17.1",
"get-port": "^5.1.1",
"html-webpack-plugin": "^4.3.0",
"husky": "^4.2.5",
"jest": "^26.1.0",
"jest": "^26.2.1",
"lint-staged": "^10.2.11",
"memfs": "^3.2.0",
"nanoid": "^3.1.10",
"nanoid": "^3.1.12",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"puppeteer": "^5.1.0",
"puppeteer": "^5.2.1",
"standard-version": "^8.0.2",
"webpack": "^4.44.0"
},
Expand Down
28 changes: 18 additions & 10 deletions src/supportWebpack4.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getWorker } from './utils';
import { getWorker, sourceMappingURLRegex } from './utils';

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

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

worker.compiler.hooks.compilation.tap('WorkerLoader', worker.compilation);
worker.compiler.hooks.compilation.tap('worker-loader', worker.compilation);
worker.compiler.runAsChild((error, entries, compilation) => {
if (error) {
return callback(error);
}

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

let workerSource = compilation.assets[worker.filename].source();

if (options.inline === 'no-fallback') {
// Remove `/* sourceMappingURL=url */` comment
workerSource = workerSource.replace(sourceMappingURLRegex, '');
}

// eslint-disable-next-line no-param-reassign
worker.factory = getWorker(
worker.file,
compilation.assets[worker.file].source(),
options
);
worker.factory = getWorker(worker.filename, workerSource, options);

if (options.inline === 'no-fallback') {
delete this._compilation.assets[worker.file];
delete this._compilation.assets[worker.filename];

// TODO improve this, we should store generated source maps files for file in `assetInfo`
if (this._compilation.assets[`${worker.filename}.map`]) {
delete this._compilation.assets[`${worker.filename}.map`];
}
}

const esModule =
Expand Down
26 changes: 17 additions & 9 deletions src/supportWebpack5.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getWorker } from './utils';
import { getWorker, sourceMappingURLRegex } from './utils';

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

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

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

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

if (options.inline === 'no-fallback') {
delete this._compilation.assets[worker.file];
delete this._compilation.assets[worker.filename];

// TODO improve this, we should store generated source maps files for file in `assetInfo`
if (this._compilation.assets[`${worker.filename}.map`]) {
delete this._compilation.assets[`${worker.filename}.map`];
}
}

if (content) {
return callback(null, content);
}

let workerSource = compilation.assets[worker.filename].source();

if (options.inline === 'no-fallback') {
// Remove `/* sourceMappingURL=url */` comment
workerSource = workerSource.replace(sourceMappingURLRegex, '');
}

// eslint-disable-next-line no-param-reassign
worker.factory = getWorker(
worker.file,
compilation.assets[worker.file].source(),
options
);
worker.factory = getWorker(worker.filename, workerSource, options);

const esModule =
typeof options.esModule !== 'undefined' ? options.esModule : true;
Expand Down
33 changes: 29 additions & 4 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function getExternalsType(compilerOptions) {
return 'var';
}

function getWorker(file, content, options) {
function getWorker(workerFilename, workerSource, options) {
let workerConstructor;
let workerOptions;

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

if (options.inline === 'fallback') {
fallbackWorkerPath = `__webpack_public_path__ + ${JSON.stringify(file)}`;
fallbackWorkerPath = `__webpack_public_path__ + ${JSON.stringify(
workerFilename
)}`;
}

return `require(${InlineWorkerPath})(${JSON.stringify(
content
workerSource
)}, ${JSON.stringify(workerConstructor)}, ${JSON.stringify(
workerOptions
)}, ${fallbackWorkerPath})`;
}

return `new ${workerConstructor}(__webpack_public_path__ + ${JSON.stringify(
file
workerFilename
)}${workerOptions ? `, ${JSON.stringify(workerOptions)}` : ''})`;
}

// Matches only the last occurrence of sourceMappingURL
const innerRegex = /\s*[#@]\s*sourceMappingURL\s*=\s*([^\s'"]*)\s*/;

/* eslint-disable prefer-template */
const sourceMappingURLRegex = RegExp(
'(?:' +
'/\\*' +
'(?:\\s*\r?\n(?://)?)?' +
'(?:' +
innerRegex.source +
')' +
'\\s*' +
'\\*/' +
'|' +
'//(?:' +
innerRegex.source +
')' +
')' +
'\\s*'
);
/* eslint-enable prefer-template */

export {
getDefaultFilename,
getDefaultChunkFilename,
getExternalsType,
getWorker,
sourceMappingURLRegex,
};
24 changes: 21 additions & 3 deletions test/__snapshots__/inline-option.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,32 @@ exports[`"inline" option should not work by default: result 1`] = `"{\\"postMess

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

exports[`"inline" option should work with "no-fallback" value: warnings 1`] = `Array []`;
13 changes: 13 additions & 0 deletions test/__snapshots__/loader.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`worker-loader should work and respect the "devtool" option ("false" value): errors 1`] = `Array []`;

exports[`worker-loader should work and respect the "devtool" option ("false" value): module 1`] = `
"export default function() {
return new Worker(__webpack_public_path__ + \\"test.worker.js\\");
};
"
`;

exports[`worker-loader should work and respect the "devtool" option ("false" value): result 1`] = `"{\\"postMessage\\":true,\\"onmessage\\":true}"`;

exports[`worker-loader should work and respect the "devtool" option ("false" value): warnings 1`] = `Array []`;

exports[`worker-loader should work with "externals": errors 1`] = `Array []`;

exports[`worker-loader should work with "externals": module 1`] = `
Expand Down
98 changes: 95 additions & 3 deletions test/inline-option.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,121 @@ describe('"inline" option', () => {
expect(getErrors(stats)).toMatchSnapshot('errors');
});

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

expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
expect(moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1).toBe(true);
expect(
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1
).toBe(true);
expect(stats.compilation.assets['test.worker.js']).toBeUndefined();
expect(result).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('should work with "no-fallback" value and the "devtool" option ("source-map" value)', async () => {
const compiler = getCompiler(
'./basic/entry.js',
{ inline: 'no-fallback' },
{ devtool: 'source-map' }
);
const stats = await compile(compiler);
const result = await getResultFromBrowser(stats);
const moduleSource = getModuleSource('./basic/worker.js', stats);

expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
expect(
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1
).toBe(true);
expect(
moduleSource.indexOf('sourceMappingURL=test.worker.js.map"') === -1
).toBe(true);
expect(stats.compilation.assets['test.worker.js']).toBeUndefined();
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
expect(result).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('should work with "no-fallback" value and the "devtool" option ("source-map" value)', async () => {
const compiler = getCompiler(
'./basic/entry.js',
{ inline: 'no-fallback' },
{ devtool: false }
);
const stats = await compile(compiler);
const result = await getResultFromBrowser(stats);
const moduleSource = getModuleSource('./basic/worker.js', stats);

expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
expect(
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') === -1
).toBe(true);
expect(stats.compilation.assets['test.worker.js']).toBeUndefined();
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
expect(result).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('should work with "fallback" value', async () => {
const compiler = getCompiler('./basic/entry.js', { inline: 'fallback' });
const stats = await compile(compiler);
const result = await getResultFromBrowser(stats);
const moduleSource = getModuleSource('./basic/worker.js', stats);

expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
expect(moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0).toBe(true);
expect(
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0
).toBe(true);
expect(stats.compilation.assets['test.worker.js']).toBeDefined();
expect(result).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

// TODO broken on webpack@5
// it.skip('should work with "fallback" value and the "devtool" option ("source-map" value)', async () => {
// const compiler = getCompiler(
// './basic/entry.js',
// { inline: 'fallback' },
// { devtool: 'source-map' }
// );
// const stats = await compile(compiler);
// const result = await getResultFromBrowser(stats);
// const moduleSource = getModuleSource('./basic/worker.js', stats);
//
// expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
// expect(
// moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0
// ).toBe(true);
// expect(stats.compilation.assets['test.worker.js']).toBeDefined();
// expect(stats.compilation.assets['test.worker.js.map']).toBeDefined();
// expect(result).toMatchSnapshot('result');
// expect(getWarnings(stats)).toMatchSnapshot('warnings');
// expect(getErrors(stats)).toMatchSnapshot('errors');
// });

it('should work with "fallback" value and the "devtool" option ("source-map" value)', async () => {
const compiler = getCompiler(
'./basic/entry.js',
{ inline: 'fallback' },
{ devtool: false }
);
const stats = await compile(compiler);
const result = await getResultFromBrowser(stats);
const moduleSource = getModuleSource('./basic/worker.js', stats);

expect(moduleSource.indexOf('inline.js') > 0).toBe(true);
expect(
moduleSource.indexOf('__webpack_public_path__ + "test.worker.js"') > 0
).toBe(true);
expect(stats.compilation.assets['test.worker.js']).toBeDefined();
expect(stats.compilation.assets['test.worker.js.map']).toBeUndefined();
expect(result).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
Expand Down
Loading

0 comments on commit 5047abb

Please sign in to comment.