-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathinline-worker-plugin.js
More file actions
128 lines (110 loc) · 4.01 KB
/
inline-worker-plugin.js
File metadata and controls
128 lines (110 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { build } from "esbuild";
import findCacheDir from "find-cache-dir";
import fs from "fs";
import path from "path";
export default function inlineWorkerPlugin(
workerPluginConfig = {},
) {
return {
name: "esbuild-plugin-inline-worker",
setup(build) {
build.onLoad(
{ filter: /\.worker.(js|jsx|ts|tsx)$/ },
async ({ path: workerPath }) => {
// const workerCode = await fs.promises.readFile(workerPath, {
// encoding: 'utf-8',
// });
const workerCode = await buildWorker(workerPath, workerPluginConfig);
return {
contents: `import inlineWorker from '__inline-worker'
export default function Worker() {
return inlineWorker(${JSON.stringify(workerCode)});
}
`,
loader: "js",
};
},
);
const options = {
name: workerPluginConfig.workerName || undefined,
...workerPluginConfig.workerArguments,
}
const inlineWorkerFunctionCode = `
export default function inlineWorker(scriptText) {
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
const { Worker } = require('worker_threads');
const fs = require('fs');
const path = require('path');
const os = require('os');
const crypto = require('crypto');
const hash = crypto.createHash('md5').update(scriptText).digest('hex').slice(0, 8);
const tempDir = os.tmpdir();
const tempFilePath = path.join(tempDir, \`worker-\${hash}-\${Date.now()}.mjs\`);
fs.writeFileSync(tempFilePath, scriptText, 'utf-8');
console.log('[inline-worker] Created temporary worker file:', tempFilePath);
const worker = new Worker(tempFilePath, ${JSON.stringify(options)});
const cleanup = () => {
try {
if (fs.existsSync(tempFilePath)) {
// fs.unlinkSync(tempFilePath);
// console.log('[inline-worker] Cleaned up temporary worker file:', tempFilePath);
}
} catch (err) {
console.error('[inline-worker] Failed to cleanup temporary file:', err);
}
};
worker.on('exit', cleanup);
// worker.on('error', cleanup);
worker.on('error', (err) => {
console.error('[inline-worker] Worker error:', err);
cleanup();
});
return worker;
} else {
const blob = new Blob([scriptText], {type: 'text/javascript'});
const url = URL.createObjectURL(blob);
const worker = new Worker(url, ${JSON.stringify(options)});
URL.revokeObjectURL(url);
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,
});
async function buildWorker(workerPath, pluginConfig) {
const scriptNameParts = path.basename(workerPath).split(".");
scriptNameParts.pop();
scriptNameParts.push("js");
const scriptName = scriptNameParts.join(".");
if (!cacheDir) {
throw new Error("Cache directory not found. Please ensure 'find-cache-dir' is installed.");
}
const bundlePath = path.resolve(cacheDir, scriptName);
if (pluginConfig.buildOptions) {
delete pluginConfig.buildOptions.entryPoints;
delete pluginConfig.buildOptions.outfile;
delete pluginConfig.buildOptions.outdir;
}
await build({
entryPoints: [workerPath],
bundle: true,
minify: true,
outfile: bundlePath,
target: "esnext",
format: "esm",
platform: "node",
...pluginConfig.buildOptions,
});
return fs.promises.readFile(bundlePath, { encoding: "utf-8" });
}