带有 Rollup 的 JS 库中的网络工作者

Web workers inside a JS library with Rollup

我正在使用 Thread.js 网络工作者在 Typescript 中构建一个 negamax 引擎。它是一个 npm 库,将由使用 webpack 构建的应用程序导入。

我正在使用 Rollup 构建引擎 - 如何导出网络工作者文件以便将它们作为单独的块复制到客户端的构建目录中?

有相应的插件:Alorel/rollup-plugin-web-worker, darionco/rollup-plugin-web-worker-loader

..但我最终从头开始,为工作人员使用单独的构建配置。这只是让我对情况有更多的控制权。

附上我用的rollup.config.worker.js

主要rollup.config.mjs 导入此文件,将其配置作为第一个构建配置。真正的构建配置使用 @rollup/plugin-replace 将 worker 的哈希注入到加载它的代码中。

/*
* Rollup config for building web worker(s)
*
* Imported by the main rollup config.
*/
import sizes from '@atomico/rollup-plugin-sizes'
import resolve from '@rollup/plugin-node-resolve'
import replace from '@rollup/plugin-replace'
import { terser } from 'rollup-plugin-terser'

import {dirname} from 'path'
import {fileURLToPath} from 'url'

const myPath = dirname(fileURLToPath(import.meta.url));

const watch = process.env.ROLLUP_WATCH;

const REGION = process.env.REGION;
if (!REGION) throw new Error("'REGION' env.var. not provided");

let loggingAdapterProxyHash;

const catchHashPlugin = {
  name: 'my-plugin',

  // Below, one can define hooks for various stages of the build.
  //
  generateBundle(_ /*options*/, bundle) {
    Object.keys(bundle).forEach( fileName => {
      // filename: "proxy.worker-520aaa52.js"
      //
      const [_,c1] = fileName.match(/^proxy.worker-([a-f0-9]+)\.js$/) || [];
      if (c1) {
        loggingAdapterProxyHash = c1;
        return;
      }
      console.warn("Unexpected bundle generated:", fileName);
    });
  }
};

const pluginsWorker = [
  resolve({
    mainFields: ["esm2017", "module"],
    modulesOnly: true       // "inspect resolved files to assert that they are ES2015 modules"
  }),
  replace({
    'env.REGION': JSON.stringify(REGION),
    //
    preventAssignment: true   // to mitigate a console warning (Rollup 2.44.0); remove with 2.45?
  }),
  //!watch && terser(),
  catchHashPlugin,

  !watch && sizes(),
];

const configWorker = {
  input: './adapters/logging/proxy.worker.js',
  output: {
    dir: myPath + '/out/worker',   // under which 'proxy.worker-{hash}.js' (including imports, tree-shaken-not-stirred)
    format: 'es',   // "required"
    entryFileNames: '[name]-[hash].js',   // .."chunks created from entry points"; default is: '[name].js'

    sourcemap: true,   // have source map even for production
  },

  plugins: pluginsWorker
}

export default configWorker;
export { loggingAdapterProxyHash }

在主配置中使用:

  replace({
    'env.PROXY_WORKER_HASH': () => {
      const hash= loggingAdapterProxyHash;
      assert(hash, "Worker hash not available, yet!");
      return JSON.stringify(hash);
    },
    //
    preventAssignment: true   // to mitigate a console warning (Rollup 2.44.0); remove with 2.45?
  }),

..并且在 Worker-loading 代码中:

const PROXY_WORKER_HASH = env.PROXY_WORKER_HASH;    // injected by Rollup build

...
new Worker(`/workers/proxy.worker-${PROXY_WORKER_HASH}.js?...`);

如果有人想要 link 整个存储库,请留言,我会 post 放在那里。它仍在不断变化。


编辑:

写完答案后我发现了这个:Building module web workers for cross browser compatibility with rollup(博客,2020 年 7 月)

TL;DR 如果您希望为 worker 使用 EcmaScript 模块,请注意!截至今天,Firefox 和 Safari 还没有支持。 source 并且 Worker 构造函数需要被告知 worker 源是 ESM。