webpack 5 并在包中包含 worker js 文件

webpack 5 and including worker js files in package

目前我有一个使用 Webpack 5 的包(我们称它为包 A)。包 A 使用一个 worker。我正在使用 worker loader 内置的新 Webpack 5。可以清楚的看到正在生成文件,放在Package A build目录下

然而,当我将包 A 作为包 B 的依赖项包含时,worker 使用的 Javascript 文件未导入到项目 B 的构建目录中。

我该如何解决这个问题? package.json 文件中是否有标识必须包含的资产文件的内容?有没有办法内联 worker.js 个文件,这样我就不用单独导入它了?

非常感谢对此的任何帮助

对于独立的工作脚本 AFAIK,没有一种干净的方法可以做到这一点。您必须指示用户将工作文件从分发文件夹复制到他们自己的构建中。或者,将文件作为单独的包托管在 CDN 上,您的原始包或其用户可以从中请求它。 quite a few caveats 这意味着对您的包将要使用的环境做出一些假设。

但是,将包与内联工作程序捆绑在一起相对容易一些。当前,Webpack 的工作假设是您捆绑了一个完整的生产项目而不是模块,因此核心包中不提供内联工作程序。您可以通过安装实际的 worker-loader 并在您的配置中传递这些设置来添加此功能:

module: {
  rules: [
    {
      test: /\.worker\.js$/,
      loader: "worker-loader",
      options: {
        inline: "no-fallback",
      },
    },
  ],
}

您可能必须更改工作文件的命名约定才能使它们正确编译 - 文档中提供了更多信息。 no-fallback 选项在这里为 inline 指定,因为我们不想为工作人员创建一个额外的文件,当有人安装我们的包时,该文件将无法使用。

所以我解决这个问题的方法是手动完成。我不认为 webpack 5 有一个加载器可以做到这一点,但添加一个 inline-worker-loader 应该很容易。

我创建了一个名为 workify.ts

的文件
// URL.createObjectURL
window.URL = window.URL || window.webkitURL;

export default (code: string): Worker => {
  let blob;
  try {
    blob = new Blob([code], { type: 'application/javascript' });
  } catch (e) {
    // Backwards-compatibility
    window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
    blob = new BlobBuilder();
    blob.append(code);
    blob = blob.getBlob();
  }
  return new Worker(URL.createObjectURL(blob));
};

此文件仅允许您将代码作为字符串并使其工作。

然后我简单地将我想要 运行 的代码放在一个以 .worker.js

结尾的文件中的一个 worker 中

然后我将以下加载程序添加到 webpack.config.js 文件

      {
        test: /\.worker\.js$/,
        type: 'asset/source',
      },

asset/source 类型只会将文件加载为字符串。

然后我可以简单地

import workerify from './workerify';
import DetectWakeup from './DetectWakeup.worker.js';

const myWorker = workerify(DetectWakeup);

如您所见,它可以很容易地变成一个加载器