Bug report
What is the current behavior?
It's known that Web Workers must be served from same origin as the page itself. Seems that even Content-Security-Policy: worker-src http://xxx has no effect on this.
We can use worker-loader to create a blob instead of a worker file.
BUT documentation https://webpack.js.org/loaders/worker-loader/ says:
DEPRECATED for v5: https://webpack.js.org/guides/web-workers/
The problem is, despite deprecation, this is the only way for now to overcome cross origin issues, documentation does not say anything about cross domain.
There are various solutions, but none of them work properly with Webpack...
If the current behavior is a bug, please provide the steps to reproduce.
I have put together the repo: https://github.com/kirill-konshin/cross-domain-worker/tree/original-issue, clone, run npm install and npm start, then just open http://localhost:3000 and check console. The demo exhibits following:
2 servers, static HTML on :3000 and Webpack Dev Server on :4001.
Page served from :3000:
<html>
<script src="http://localhost:4001/entry.js"></script>
</html>
JS served from :4001:
// entry.js
const worker = new Worker(new URL('./worker', import.meta.url));
// worker.js
console.log('Foo');
If you open the http://localhost:3000, you'll get:
Uncaught DOMException: Failed to construct 'Worker': Script at 'http://localhost:4000/test/src_worker_js.js' cannot be accessed from origin 'http://localhost:3000'.
Documentation does not suggest any solution for this.
What is the expected behavior?
Two options:
- Provide a good example how to make it work using modern approach or
- Un-deprecate
worker-loader and provide documentation when to use it, and hopefully fix the additional issue
Additional issue
If 2nd approach will be taken, I'd like to report an additional problem, but the loader repo is archived, so I'll put it here, with the workaround.
Since worker-loader will create a blob, it has no access to proper __webpack_public_path__, in worker it will be blob:http://localhost:3000/, e.g. host origin, so worker loaded this way won't have access to assets.
I've assembled a short demo, where I added devServer.proxy which can serve same content from /test/ and / to mimic how content can be served from different CDNs and paths using output.publicPath='auto'.
Solution is to postMessage proper __webpack_public_path__ from main thread, and then wrap all asset requests in the worker:
// entry.js
const worker = new Worker('./worker', import.meta.url);
worker.postMessage({msg: 'base', payload: __webpack_public_path__});
// worker.js
function joinSegments(a, b) {
return '/' + a.split('/').concat(b.split('/')).filter(Boolean).join('/');
}
function replaceOrigin(blob, base) {
const url = new URL(blob.replace('blob:', ''));
const search = url.searchParams.toString();
const baseUrl = new URL(base);
return new URL(joinSegments(baseUrl.pathname, url.pathname) + (search ? '?' + search : ''), baseUrl.origin).toString();
}
self.onmessage = ({data: {msg, payload}}) => {
if (msg === 'base') {
const image = require('./package.png');
console.log(payload); // returns http://localhost:4001/test/ which is right
console.log(image); // returns blob:http://localhost:3000/xxx.png, should be localhost:4001
console.log(__webpack_public_path__); // returns blob:http://localhost:3000/, should be http://localhost:4001/test/
const imageProper = replaceOrigin(image, payload);
console.log(imageProper);
fetch(imageProper).then(r => console.log(r));
}
};
Very awkward, but works well.
Hopefully others can either copy-paste the hack, or, fingers crossed, worker-loader can be revived and can provide some normal way to recover dynamic public paths.
Bug report
What is the current behavior?
It's known that Web Workers must be served from same origin as the page itself. Seems that even
Content-Security-Policy: worker-src http://xxxhas no effect on this.We can use
worker-loaderto create a blob instead of a worker file.BUT documentation https://webpack.js.org/loaders/worker-loader/ says:
DEPRECATED for v5: https://webpack.js.org/guides/web-workers/The problem is, despite deprecation, this is the only way for now to overcome cross origin issues, documentation does not say anything about cross domain.
There are various solutions, but none of them work properly with Webpack...
importstatements etc.)If the current behavior is a bug, please provide the steps to reproduce.
I have put together the repo: https://github.com/kirill-konshin/cross-domain-worker/tree/original-issue, clone, run
npm installandnpm start, then just openhttp://localhost:3000and check console. The demo exhibits following:2 servers, static HTML on
:3000and Webpack Dev Server on:4001.Page served from
:3000:JS served from
:4001:If you open the
http://localhost:3000, you'll get:Uncaught DOMException: Failed to construct 'Worker': Script at 'http://localhost:4000/test/src_worker_js.js' cannot be accessed from origin 'http://localhost:3000'.Documentation does not suggest any solution for this.
What is the expected behavior?
Two options:
worker-loaderand provide documentation when to use it, and hopefully fix the additional issueAdditional issue
If 2nd approach will be taken, I'd like to report an additional problem, but the loader repo is archived, so I'll put it here, with the workaround.
Since
worker-loaderwill create a blob, it has no access to proper__webpack_public_path__, in worker it will beblob:http://localhost:3000/, e.g. host origin, so worker loaded this way won't have access to assets.I've assembled a short demo, where I added
devServer.proxywhich can serve same content from/test/and/to mimic how content can be served from different CDNs and paths usingoutput.publicPath='auto'.Solution is to
postMessageproper__webpack_public_path__from main thread, and then wrap all asset requests in the worker:Very awkward, but works well.
Hopefully others can either copy-paste the hack, or, fingers crossed,
worker-loadercan be revived and can provide some normal way to recover dynamic public paths.