Web Worker Same Origin Policy Error Reporting Solution

Introduction

Recently, when a friend was researching webpack 5 to package the umd library, he found that the web worker could not be inlined into a js file. Originally, if the project dependencies were all under the same domain name, there would be no problem in using it. However, web workers have strict same-origin policy restrictions. When using CDN under other domain names to load this umd library, a same-origin policy error will be reported when loading web worker files asynchronously. The general error report is as follows:

Uncaught DOMException: Failed to construct 'Worker': Script at 'XXX/js/worker.js' cannot be accessed from origin 'http://127.0.0.1:5500'.

Because webpack 4 supports configuring the parameter of worker-loader as inline:'fallback', such as this configuration

module.exports = {
  module: {
    rules: [
      {
        test: /\.worker\.(c|m)?js$/i,
        loader: "worker-loader",
        options: {
          inline: "fallback",
        },
      },
    ],
  },
};

As of now, webpack 5 does not support this configuration. Without the inline function, we can only think of other ways.

Solution

Update worker usage

Use new Worker(URL) to create a new worker process, but this URL can be used as an entry point to explore possible transformation ideas. Before the transformation, we are familiar with the general usage scenarios.

  1. Direct quote

Under normal circumstances, you can directly use new Worker a local file to use the worker, for example, we create a new local file

// worker.js
console.log("local worker");

Then reference this worker.js file in the html file

<!-- index.html -->
<script type="module">
  new Worker("./worker.js");
</script>

This is the normal output, please note that the browser console needs to switch to the worker process to see the print.

The figure below shows that you can switch JavaScript context under the console, or switch Threads directly under Sources.

web worker

So the problem lies here. If you directly quote it, the local file in the same domain is fine. If it is a file on the remote CDN, the problem will come out.

<!-- index.html -->
<script type="module">
  new Worker(
    "https://gcore.jsdelivr.net/gh/openHacking/static-files@main/js/worker.js"
  );
</script>

After running, the console reported a same-origin policy error

Uncaught DOMException: Failed to construct 'Worker': Script at 'https://gcore.jsdelivr.net/gh/openHacking/static-files@main/js/worker.js' cannot be accessed from origin 'http://127.0 .0.1:5500'.
    at http://127.0.0.1:5500/index.html:14:9

So we now try to avoid this error

  1. Pass in the blob

We found that the first input parameter of new Worker is a script address, which also supports blob addresses. We can find a way to convert the content of the js file into a blob, and then convert the blob into a URL. Let's experiment with a plain string script first

<!-- index.html -->
<script type="module">
  // convert string to blob
  const str2blob = (txt) => new Blob([txt]);
  // blob converted to URL
  const url = URL.createObjectURL(str2blob('console.log("string worker")'));
  // Create a new Worker
  new Worker(url);
</script>

This can output string worker normally

  1. Parse the remote script

Furthermore, it is impossible for our worker script to have only a few strings, or to write code with strings is not standardized and cannot be debugged, so we still need to load a script file similar to worker.js. Here we try to use fetch parse file as blob

<script type="module">
  fetch(
    "https://gcore.jsdelivr.net/gh/openHacking/static-files@main/js/worker.js"
  )
    .then((response) => response.blob())
    .then((blob) => {
      const url = URL.createObjectURL(blob);
      new Worker(url);
    });
</script>

In this way, our remote CDN loads the worker file to avoid the same-origin policy and reports an error.

Do not use CDN

Of course, the above idea is based on the transformation of the source code. In some cases, it is not easy to modify the source code, so we can only put all js resource files in the project directory, that is, under the same domain name, to prevent the same source policy error

Remove worker

If you still need to use CDN and don't want to change the source code too much, it depends on whether your requirements for workers are important. If it is not important, you can delete the part of the source code that uses worker to avoid reporting errors.

Conclusion

The above is some experience about the use of web workers summarized by me. If you have better discoveries and ideas, please share them.

Reference

Comments