mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 19:03:46 +02:00
99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
// Adapted from https://github.com/mitschabaude/esbuild-plugin-inline-worker
|
|
|
|
import * as esbuild from 'esbuild';
|
|
import findCacheDir from 'find-cache-dir';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
export function inlineWorkerPlugin(extraConfig: esbuild.BuildOptions): esbuild.Plugin {
|
|
return {
|
|
name: 'esbuild-plugin-inline-worker',
|
|
|
|
setup(build) {
|
|
build.onLoad(
|
|
{ filter: /\.worker\.(js|jsx|ts|tsx)$/ },
|
|
async ({ path: workerPath }) => {
|
|
const workerCode = await buildWorker(workerPath, extraConfig);
|
|
return {
|
|
contents: `import inlineWorker from '__inline-worker'
|
|
export default function Worker() {
|
|
return inlineWorker(${JSON.stringify(workerCode)});
|
|
}
|
|
`,
|
|
loader: 'js',
|
|
};
|
|
},
|
|
);
|
|
|
|
const inlineWorkerFunctionCode = `
|
|
export default async function inlineWorker(scriptText) {
|
|
if (typeof Worker !== 'undefined' && typeof Bun === 'undefined') {
|
|
// Browser, Deno
|
|
|
|
const blob = new Blob([scriptText], { type: "text/javascript" });
|
|
const url = URL.createObjectURL(blob);
|
|
const worker = new Worker(url, { type: typeof Deno !== 'undefined' ? 'module' : undefined }); // module for Deno
|
|
URL.revokeObjectURL(url);
|
|
return worker;
|
|
} else {
|
|
// Node, Bun (Bun's Worker is flaky, worker_threads works much better)
|
|
|
|
let Worker;
|
|
try {
|
|
Worker = (await import('worker_threads')).Worker;
|
|
} catch {
|
|
const workerModule = 'worker_threads';
|
|
Worker = require(workerModule).Worker;
|
|
}
|
|
|
|
const worker = new Worker(scriptText, { eval: true });
|
|
|
|
return worker;
|
|
}
|
|
}
|
|
`;
|
|
|
|
build.onResolve({ filter: /^__inline-worker$/ }, ({ path }) => {
|
|
return { path, namespace: 'inline-worker' };
|
|
});
|
|
build.onLoad({ filter: /.*/, namespace: 'inline-worker' }, () => {
|
|
return { contents: inlineWorkerFunctionCode, loader: 'js' };
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
const cacheDir = findCacheDir({
|
|
name: 'esbuild-plugin-inline-worker',
|
|
create: true,
|
|
});
|
|
if (cacheDir === undefined) {
|
|
throw new Error('Cache directory not found.');
|
|
}
|
|
|
|
async function buildWorker(workerPath: string, extraConfig: esbuild.BuildOptions) {
|
|
const scriptNameParts = path.basename(workerPath).split('.');
|
|
scriptNameParts.pop();
|
|
scriptNameParts.push('js');
|
|
const scriptName = scriptNameParts.join('.');
|
|
const bundlePath = path.resolve(cacheDir!, scriptName);
|
|
|
|
if (extraConfig) {
|
|
delete extraConfig.entryPoints;
|
|
delete extraConfig.outfile;
|
|
delete extraConfig.outdir;
|
|
}
|
|
|
|
await esbuild.build({
|
|
entryPoints: [workerPath],
|
|
bundle: true,
|
|
minify: true,
|
|
outfile: bundlePath,
|
|
target: 'es2017',
|
|
format: 'esm',
|
|
...extraConfig,
|
|
});
|
|
|
|
return fs.promises.readFile(bundlePath, { encoding: 'utf-8' });
|
|
}
|