Ad

Getting Failed To Construct 'Worker' With JS Worker File Located On Other Domain

- 1 answer

I am using react-pdf to render a PDF file inline on my Django/Wagtail website.

To do this, I create a div in my HTML template with ID react, and I run a file called index.js which is a pretty straightforward React file that creates a DocumentViewer element and uses ReactDom to render it to the div with id 'react'.

I get an error when running my website on production when loading the worker file from my main bundle, specifically an error about how script worker.js cannot be accessed from origin 'example.com'

The exact code is not really relevant (although I can post it if necessary, but the thing that's giving me issues is loading the react-pdf worker.

I use the following import statement as the docs recommend:

import {Document, Outline, Page} from 'react-pdf/dist/entry.webpack';

I then use webpack to bundle and minify this file, with the following webpack.config.js:

var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');

module.exports = {
  context: __dirname,

  entry: './project/app_name/static/js/index.js',

  output: {
      path: path.resolve('./project/app_name/static/bundles/'),
      publicPath: '/static/bundles/',
      filename: "[name]-[hash].js",
  },

  plugins: [
    new BundleTracker({filename: './webpack-stats.json'}),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      }
    ]
  },
  resolve: {
    extensions: ['*', '.js', '.jsx']
  }

};

This creates two files in the static/bundles folder of my Django application, main-<hash>.js and <hash>.worker.js.

The main-<hash>.js file creates a worker like this:

return new Worker(r.p+"<hash>.worker.js")

When I run my Django installation on my local machine, where I serve static files from the localhost there are no issues, which is pretty logical, since all files have the same origin.

However when I run it in production, where I serve my static files from a DigitalOcean space, Chrome produces the following error:

main-.js:38 Uncaught DOMException: Failed to construct 'Worker': Script at 'https://ams3.digitaloceanspaces.com/-media/static/bundles/.worker.js' cannot be accessed from origin 'https://www.example.com'.

I have already checked the CORS headers on that space, and everything seems to be in order.

When I use the curl command like this:

curl -v 'https://ams3.digitaloceanspaces.com/<project>-media/static/bundles/<hash>.worker.js' -X OPTIONS -H "Origin:https://example.com" -H "Access-Control-Request-Method: GET,PUT,HEAD,POST"

I get a 200 OK response.

I have no idea why Chrome would reject the loading of this script.

Is there something I'm missing in my webpack config, CORS settings or any other way browsers handle loading external scripts that I'm missing?

Ad

Answer

For anyone reading this: I figured out what the problem is.

Most browsers don't allow you to load a Worker from an external source, even if the CORS headers are all in order, the script loading is loaded from the same source as the worker, and the source is in my control.

Chrome, Firefox, and Safari all gave different errors, which was why I was confused as to what exactly happened.

The way I fixed this was by not loading the external worker, and running the code inline.

Two other ways to fix this are:

  • Serving the worker.js file from the same origin as the webpage.
  • Creating a worker through a blob URL (Like in this link). The worker I used was loaded from a package inside my dependencies, I tried to configure Webpack to load this worker like this, but I could not get it to work.

So in the end I opted for not loading the worker at all.

Ad
source: stackoverflow.com
Ad