【问题标题】:Web Workers - How To Import ModulesWeb Workers - 如何导入模块
【发布时间】:2017-10-22 10:47:48
【问题描述】:

我正在使用 ES2015 导入/导出模块。

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

worker.js

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

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

当我在模块“abc.js”中导出函数时,我不确定如何使用旧的(显然即将淘汰)语法来使用它们:

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

那么,我的问题是,我们如何将新的导入模块语法与工作人员一起使用?

第二个问题是,importScripts 从没有导出全局对象父级的模块导入时会导入什么?

【问题讨论】:

    标签: javascript import module ecmascript-6 web-worker


    【解决方案1】:

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

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

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

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

    见:https://html.spec.whatwg.org/#module-worker-example

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

    • Firefox: 开发中? 请投票!
    • Chromium 浏览器:
      Dedicated Workers自 80 版起可用 ✔️
      Shared Workers自 83 版起可用 ✔️
      Service Workers : 自 91 版起可用 ✔️
    • Webkit:
      Safari 桌面版:自 Safari 14.1 起可用 ✔️
      Safari Mobile (iOS):自 Safari 15 起可用 ✔️

    【讨论】:

    • 如何知道什么时候支持?
    • 查看我更新的答案。 Chromium 正在积极开发它。
    • 啊,所以只有新的Worker(..)需要指定“模块”。实际的工作代码可以正常导入/导出。这是正确的吗?听起来像节点的 .mjs :)
    • 它将与 Chromium 80 一起发货,Chrome 80 计划在 2020 年 2 月 4 日稳定。好吧……。
    【解决方案2】:

    worker 中的 ES 模块已经在 Chrome 中可用,启用 Experimental Web Platform Features,在启动 chrome 时使用正确的标志:

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

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

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

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

    【讨论】:

    • 也改为在chrome://flags/ 中以一个标志开始,然后搜索Experimental Web Platform features 或类似的东西
    【解决方案3】:

    对我来说,分配给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;
    

    通过这种方式,它可以在worker内部访问。 (在 chrome 中测试)

    【讨论】:

    • 你从哪里得到require
    • 我认为这是另一个(疯狂!)工作流已将“require”修改为可行的解决方案的情况。卷起?还是更有可能是 Webpack?
    • 是的,webpack。就我而言,它是使用 webpacker gem 的 rails 应用程序,它使用 webpack :)
    • abcImported.js 是单独托管的文件吗?
    【解决方案4】:

    2020:

    Chrome 80 has shipped module workers in February 2020(Chrome 82 将为共享工作者提供模块)。 Firefox/Safari 目前不支持这些功能:tests

    您可以使用希望使用 import-from-worker lib 来为您完成繁重的工作(现在,您需要检查对工作模块的支持并自己执行回退)。

    【解决方案5】:

    截至 11 月 21 日,在 worker 中导入模块似乎仍然很不稳定。一种解决方案是使用汇总从您的工作人员生成 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 正在做浏览器应该做的工作。 这对我来说效果很好。当然,代码大小会增加,因为模块代码也被复制到 worker 中。但它仍然是 DRY,因为代码是由 rollup 生成的。

    【讨论】:

      猜你喜欢
      • 2019-05-03
      • 2018-08-29
      • 2020-12-06
      • 2020-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多