问题
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