bundle web workers as integral part of npm package with single file webpack output

匆匆过客 提交于 2021-02-10 06:29:09

问题


I am writing an npm package which is a plugin for the popular library leafletjs. I am using webpack to bundle the package. I want this package to be able to spawn and destroy some web workers on command. The web worker code is part of my source files. But I want to be able to distribute my package both as an npm module, or through a cdn, meaning it must be compiled down to a singular file that can be included through an HTML header. I am using webpack to do it. So lets say I have a worker file:

// sample.worker.js

import { doSomeStuff } from './algorithm.js';

onmessage = function (e) {
  const results = doSomeStuff(e.data)
  postMessage({
    id: e.data.id,
    message: results',
  });
};

Fairly simple, but an important point here is that my worker is actually importing some code from an algorithm file, which is in turn importing some node modules. My worker is used in the main module somewhere, like this:

// plugin.js

import SampleWorker from 'worker-loader!./workers/dem.worker.js';

export function plugin(){
  // do some stuff
  const worker = new SampleWorker()
  worker.postMessage(someData);
  worker.onmessage = (event) => {};
}

My webpack config looks like this:

module.exports = {
  entry: './src/index',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'my-plugin.js',
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.json'],
  },
  module: {
    rules: [
      {
        test: /\.worker\.js$/,
        loader: 'worker-loader',
        options: {
          inline: 'fallback',
        },
      },
      {
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
    ],
  },
  externals: { ... },
  plugins: { ... }
};

This doesn't work as is - webpack tries to bundle the main bundle and each worker script file under the same name. Changing to filename: '[name].js' under output fixes this issue, but gives me many files - one for the main bundle, and another file for each worker file in my source code.

Reading the webpack options, I thought that using the inline: 'fallback' option would actually create a Blob for each worker and bundle that into the main output file. That is not happening.

So far my solution is to write my workers as blobs, like this:

// workers.js

const workerblob = new Blob([`

  // cannot import in a blob! 
  // have to put algorithm.js code here, copy in any external module code here

  onmessage = function (e) {
    const results = doSomeStuff(e.data)
    postMessage({
      id: e.data.id,
      message: results,
    });
  };

`])

export const sampleWorker = URL.createObjectURL(workerblob);

// my-plugin.js
import { sampleWorker } from 'workers.js'

const worker = new Worker(sampleWorker)

This does in fact work - webpack now outputs 1 single file which includes the worker code. Using a modified version of this from this answer, I can at least place my code inside a function( ...code... ){}.toString() format, so I can at least get intellisense, syntax highlighting, etc. But I cannot use imports.

How can I use webpack to bundle my workers so that the entire bundle ends up in 1 file, worker code and all?

来源:https://stackoverflow.com/questions/64438523/bundle-web-workers-as-integral-part-of-npm-package-with-single-file-webpack-outp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!