我正在开发一个我想在CDN上托管的库。该库将用于跨多个服务器的许多不同域。库本身包含一个脚本(我们现在称之为script.js),它加载一个web worker(worker.js)。
加载库本身非常简单:只需将<script type="text/javascript" src="http://cdn.mydomain.com/script.js"></script>
标记添加到我要使用该库的域(www.myotherdomain.com)。但是,由于库正在从http://cdn.mydomain.com/worker.js new Worker('http://cdn.mydomain.com/worker.js')
加载一个worker,我得到一个SecurityException。在cdn.mydomain.com上启用了CORS。
对于Web worker,不允许在远程域上使用Web worker。使用CORS无济于事:浏览器似乎忽略它,甚至不执行预检检查。
解决这个问题的方法是执行XMLHttpRequest以获取worker的源,然后创建一个BLOB url并使用此url创建一个worker。这适用于Firefox和Chrome。但是,这似乎不适用于Internet Explorer或Opera。
解决方案是将工作人员放在www.myotherdomain.com上或放置一个代理文件(它只是使用XHR或importScripts从cdn加载工作人员)。我不喜欢这个解决方案:它要求我在服务器上放置其他文件,因为库在多个服务器上使用,所以更新很困难。
我的问题包括两个解析:
答案 0 :(得分:15)
对于那些发现这个问题的人:
YES。
绝对可能:诀窍是利用远程域上的iframe并通过postMessage与之通信。远程iframe(托管在cdn.mydomain.com上)将能够加载webworker(位于cdn.mydomain.com/worker.js),因为它们都具有相同的来源。 然后,iframe可以充当postMessage调用之间的代理。但是,script.js将负责过滤消息,因此只处理有效的工作者消息。
缺点是通信速度(和数据传输速度)确实会受到性能影响。
简而言之:
src="//cdn.mydomain.com/iframe.html"
new Worker("worker.js")
并充当来自窗口和message
的{{1}}事件的代理(反之亦然) worker.postMessage
和来自窗口的iframe.contentWindow.postMessage
事件与工作人员进行通信。 (正确检查多个工人的正确起源和工人身份)答案 1 :(得分:5)
最好是动态生成一个简单的工作脚本,该工作脚本将在内部调用importScripts()
,不受此跨域限制的限制。
要了解为什么不能将跨域脚本用作Worker初始化脚本,请参见this answer。基本上,Worker上下文将其自身的来源设置为该脚本之一。
// The script there simply posts back an "Hello" message
// Obviously cross-origin here
const cross_origin_script_url = "https://greggman.github.io/doodles/test/ping-worker.js";
const worker_url = getWorkerURL( cross_origin_script_url );
const worker = new Worker( worker_url );
worker.onmessage = (evt) => console.log( evt.data );
URL.revokeObjectURL( worker_url );
// Returns a blob:// URL which points
// to a javascript file which will call
// importScripts with the given URL
function getWorkerURL( url ) {
const content = `importScripts( "${ url }" );`;
return URL.createObjectURL( new Blob( [ content ], { type: "text/javascript" } ) );
}
答案 2 :(得分:2)
无法从其他域加载网络工作者。
类似于您的建议,您可以进行访存调用,然后获取该JS并对其进行base64。这样做可以使您做到:
const worker = new Worker(`data:text/javascript;base64,${btoa(workerJs)}`)
您可以在此处找到有关数据URI的更多信息:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs。
这是我更喜欢的解决方法,因为它不需要像带有消息代理的iframe这样的疯狂工具,而且只要您从CDN正确设置了CORS,就可以轻松上手。