使用react-pdf时无法使用位于其他域上的JS worker文件构造'Worker'

时间:2019-09-25 13:05:35

标签: django reactjs webpack cors digital-ocean

我正在使用react-pdf在Django / Wagtail网站上内嵌呈现PDF文件。

为此,我在HTML模板中创建了一个ID为react的div,然后运行一个名为index.js的文件,这是一个非常简单的React文件,它创建一个DocumentViewer元素并使用ReactDom将其呈现到div ID为“ react”的div。

从主捆绑包中加载工作文件时,在生产环境中运行我的网站时出现错误,特别是关于如何无法从来源'example.com'访问脚本worker.js的错误

确切的代码并没有真正的意义(尽管我可以在必要时将其发布,但是给我带来麻烦的是加载react-pdf worker。

我将以下导入语句用作the docs recommend

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

然后,我使用webpack通过以下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']
  }

};

这将在我的Django应用程序的static/bundles文件夹中创建两个文件,分别为main-<hash>.js<hash>.worker.js

main-<hash>.js文件创建了如下工作器:

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

当我在本地计算机上运行Django安装时,我在本地主机上提供静态文件,因此没有问题,这是合乎逻辑的,因为所有文件的来源都相同。

但是,当我在生产环境中运行它(从DigitalOcean空间提供静态文件)时,Chrome会产生以下错误:

  

main-.js:38未捕获的DOMException:无法构造'Worker':   脚本在   'https://ams3.digitaloceanspaces.com/-media / static / bundles / .worker.js'   不能从来源'https://www.example.com'访问。

我已经检查了该空间上的CORS标头,一切似乎都井然有序。

当我像这样使用curl命令时:

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"

我得到200 OK响应。

我不知道为什么Chrome会拒绝加载该脚本。

我的Webpack配置,CORS设置或浏览器处理加载我丢失的外部脚本的任何其他方式中是否缺少某些内容?

2 个答案:

答案 0 :(得分:0)

对于阅读此书的任何人:我知道了问题所在。

大多数浏览器都不允许您从外部源加载Worker,即使CORS标头都井然有序,脚本加载是从与Worker相同的源加载的,而该源在我的控制之下。

Chrome,Firefox和Safari都给出了不同的错误,这就是为什么我对到底发生了什么感到困惑。

我解决此问题的方法是不加载外部工作程序,并内联运行代码。

其他两种解决方法:

  • 从与网页相同的来源提供worker.js文件。
  • 通过Blob URL创建工作程序(类似于this link)。 我使用的工作程序是从依赖项中的程序包中加载的,我尝试将Webpack配置为像这样加载此工作程序,但是我无法使其正常工作。

所以最后我选择完全不加载工作程序。

答案 1 :(得分:0)

使用 blob URL 支持 CROS 工作线程,您可以这样做:

function workerCros(url) {
  const iss = "importScripts('" + url + "');";
  return URL.createObjectURL(new Blob([iss]));
}

const workerUrl = workerCros(new URL(workerFilePath, window.location).href);
const worker = new Worker(workerUrl);