无法使用位于其他域的 JS 工作文件构造 'Worker'
Getting Failed to construct 'Worker' with JS worker file located on other domain
我正在使用 react-pdf 在我的 Django/Wagtail 网站上内联呈现 PDF 文件。
为此,我在我的 HTML 模板中创建了一个 div ID 反应,我 运行 一个名为 index.js
的文件,这是一个非常简单的 React创建一个 DocumentViewer 元素并使用 ReactDom 将其呈现到 ID 为 'react'.
的 div 的文件
当从我的主包加载工作文件时 运行 将我的网站投入生产时,我得到一个错误,特别是关于脚本 worker.js 无法从原点访问的错误 'example.com'
确切的代码并不是真正相关的(尽管我可以 post 如果需要,但给我带来问题的是加载 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 space 提供我的静态文件时,Chrome 会产生以下错误:
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'.
我已经检查了 space 上的 CORS headers,一切似乎都井井有条。
当我像这样使用 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 设置或浏览器处理加载外部脚本的任何其他方式是否遗漏了我遗漏的内容?
致所有读到这篇文章的人:我知道问题出在哪里了。
大多数浏览器不允许你从外部源加载一个Worker,即使CORS headers都是有序的,脚本加载是从与worker相同的源加载的,源在我的控制。
Chrome、Firefox 和 Safari 都给出了不同的错误,这就是为什么我对到底发生了什么感到困惑。
我解决这个问题的方法是不加载外部工作者,运行 内联代码。
解决此问题的其他两种方法是:
- 从与网页相同的来源提供 worker.js 文件。
- 通过 blob 创建一个 worker URL(如 this link)。
我使用的 worker 是从我的依赖项中的包加载的,我试图配置 Webpack 来加载这个 worker,但我无法让它工作。
所以最后我选择了完全不加载worker。
用 blob 支持 CROS worker URL,你可以这样做:
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);
我正在使用 react-pdf 在我的 Django/Wagtail 网站上内联呈现 PDF 文件。
为此,我在我的 HTML 模板中创建了一个 div ID 反应,我 运行 一个名为 index.js
的文件,这是一个非常简单的 React创建一个 DocumentViewer 元素并使用 ReactDom 将其呈现到 ID 为 'react'.
当从我的主包加载工作文件时 运行 将我的网站投入生产时,我得到一个错误,特别是关于脚本 worker.js 无法从原点访问的错误 'example.com'
确切的代码并不是真正相关的(尽管我可以 post 如果需要,但给我带来问题的是加载 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 space 提供我的静态文件时,Chrome 会产生以下错误:
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'.
我已经检查了 space 上的 CORS headers,一切似乎都井井有条。
当我像这样使用 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 设置或浏览器处理加载外部脚本的任何其他方式是否遗漏了我遗漏的内容?
致所有读到这篇文章的人:我知道问题出在哪里了。
大多数浏览器不允许你从外部源加载一个Worker,即使CORS headers都是有序的,脚本加载是从与worker相同的源加载的,源在我的控制。
Chrome、Firefox 和 Safari 都给出了不同的错误,这就是为什么我对到底发生了什么感到困惑。
我解决这个问题的方法是不加载外部工作者,运行 内联代码。
解决此问题的其他两种方法是:
- 从与网页相同的来源提供 worker.js 文件。
- 通过 blob 创建一个 worker URL(如 this link)。 我使用的 worker 是从我的依赖项中的包加载的,我试图配置 Webpack 来加载这个 worker,但我无法让它工作。
所以最后我选择了完全不加载worker。
用 blob 支持 CROS worker URL,你可以这样做:
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);