Web Workers - 如何导入module

IT技术 javascript import module ecmascript-6 web-worker
2021-02-22 19:56:52

我正在使用 ES2015 导入/导出module。

在我的工作文件中,当我尝试像往常一样导入函数时:

工人.js

import { a, b, c } from "./abc.js";

我收到错误: SyntaxError: import declarations may only appear at top level of a module

当我在我的module 'abc.js' 中导出函数时,我不确定如何使用旧的(并且显然正在淘汰)语法来使用它们:

self.importScripts( "/app/abc.js" );

所以,我的问题是,我们如何对工作人员使用新的导入module语法?

第二个问题是,importScripts当它从没有导出全局对象父级的module中导入时,import into 是什么?

5个回答

Workers 中的 ES2015 module在Safari 和 Chromium 浏览器中可用。

如果其他浏览器/版本是您的目标,您仍然需要使用importScripts().

如果可用,您可以像这样创建一个module工作者:

new Worker("worker.js", { type: "module" });

请参阅:https : //html.spec.whatwg.org/#module-worker-example

这些是每个浏览器的错误报告:

  • Firefox : 开发中🛑请投票!
  • Chromium 浏览器:
    专用工作线程从 80 版本开始可用✔️
    共享工作线程从 83 版本开始可用✔️
    服务工作线程从 91 版本开始可用✔️
  • Webkit
    Safari 桌面版:自 Safari 14.1可用✔️
    Safari 移动版(iOS): 自 Safari 15可用✔️
如何知道什么时候会得到支持?
2021-04-23 19:56:52
请参阅我更新的答案。Chromium 正在积极开发它。
2021-05-06 19:56:52
啊,所以只有 new Worker(..) 需要指定“module”。实际的工作代码可以正常导入/导出。这是正确的吗?听起来像节点的 .mjs :)
2021-05-14 19:56:52
它将与 Chromium 80 一起发货,Chrome 80 计划在 2020 年 2 月 4 日稳定。好吧……。
2021-05-19 19:56:52

2020:

Chrome 80 已于 2020 年 2 月推出了module工作器(Chrome 82 将为共享工作器提供module)。Firefox/Safari 目前不支持这些功能:测试

您可能想使用import-from-worker lib 为您完成繁重的工作(目前,您需要检查对工作程序中module的支持并自己进行回退)。

工人中的 ES module已经在 Chrome 中可用,启用实验性 Web 平台功能,在启动 chrome 时使用适当的标志:

chrome.exe --enable-experimental-web-platform-features

这是将工作脚本作为module加载所需的语法:

new Worker( 'my-worker.js', { type : 'module' } );

这个功能已经开发了将近一年,应该很快就会可用,不需要特殊的标志,但是,还没有正式的发布日期。

也不是从一个标志开始,chrome://flags/然后搜索Experimental Web Platform features或类似的选项
2021-05-14 19:56:52

截至 11 月 21 日,在工作人员中导入module似乎仍然不稳定。一种解决方案是使用汇总从您的工作人员生成 IIFE,如下所示:

//worker.js
import { MyModule } from 'my-module.js'
onconnect = async (e) => {
    var port = e.ports[0];
    MyModule.func()

    port.onmessage = (e) => {
        port.postMessage("Hi App");
    }
}

//rollup config
export default [
{
        'input': 'worker.js',
        'output': {
            'file': 'dist/worker.js',
            'format': 'iife'
        },
 },
]


//dist/worker.js (rollup output)

(function () {
    'use strict';
    //MyModule code here, generated by rollup
    
    MyModule.func()
    onconnect = async (e) => {
        var port = e.ports[0];
        port.onmessage = (e) => {
            port.postMessage("Hi App");
        };
    };

}());

//main app

const worker = new SharedWorker("/dist/worker.js");
worker.port.onmessage = (e) => {
    console.log('Message received from worker: ' + e.data);
}
worker.port.postMessage("Hi worker");

本质上 rolllup 正在做浏览器应该做的工作。这对我来说效果很好。当然,代码大小会增加,因为module代码也被复制到工作线程中。但它仍然是 DRY 的,因为代码是由 rollup 生成的。

对我来说,self.工作得很好。我已经把导入到另一个 js 文件:abcImported.js

import { a, b, c } from "./abc.js";

export {  a, b, c };

在服务工作者中:

self.a = require('abcImported.js').a;
self.b = require('abcImported.js').b;

通过这种方式,它可以在工作人员内部访问。(在铬测试)

abcImported.js文件是否单独托管?
2021-04-23 19:56:52
你从哪里来require
2021-04-26 19:56:52
是的,网络包。就我而言,它是使用 webpacker gem 的 rails 应用程序,它使用 webpack :)
2021-05-02 19:56:52
我认为这是另一种(疯狂的!)案例,其中工作流已将“要求”修改为有效的解决方案。卷起?或者更可能是 Webpack?
2021-05-10 19:56:52