Skip to content

Cross-origin Web Workers still require worker-loader #16696

Description

@kirill-konshin

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:

  1. Provide a good example how to make it work using modern approach or
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions