我正在创建一个主要在 Web Worker 中运行的库(尽管它也可以在主线程中运行)。我希望使用我的库的应用程序(假设他们使用 Vite 构建应用程序)能够创建与其主应用程序包分开的自定义代码包。应用程序应该能够以某种编程方式获取此自定义代码包的 URL,然后将其传递给 Web Worker(通过库 API)。然后,Web Worker 动态导入该包。
本质上,我需要一种好方法来允许应用程序将自定义代码注入到我的库的 Web Worker 中。是否有支持的方法可以通过 Vite 来实现这一点?
我发现了一种有点hacky的方法,但它只有在运行时才能在开发模式下工作
vite
。它以预期的方式(导入 Web Worker)和非预期的方式(生成和获取单独的非 Web Worker 包的 URL)使用 Vite 的 Web Worker API。
应用程序的index.ts文件
// Import the library's worker itself with Vite's Web Worker import API
import LibraryWorker from '../library/LibraryWorker.js?worker';
// Use the same Web Worker import API but in URL mode
// This tell's Vite to create a separate bundle for CustomCodeModule.js
// but only return the URL to that bundle
import customModuleBundleUrl from './CustomCodeModule.js?worker&url';
(async () => {
console.log('customModuleBundle', customModuleBundleUrl);
// Start the worker
const worker = new LibraryWorker();
// Wait some time for worker to be ready
await sleep(1000);
// Send the custom module bundle to the Worker
worker.postMessage({
type: 'init',
url: customModuleBundleUrl,
});
})();
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
图书馆的LibraryWorker.ts
// Listen for the `init` message
self.addEventListener('message', (event) => {
if (event.data.type === 'init') {
// Dynamically import the custom bundle URL
import(event.data.url /* @vite-ignore */).then(({ CustomCode }) => {
// Execute the module exported by the custom bundle
const customCode = new CustomCode();
customCode.run();
});
}
});
应用程序的CustomCodeModule.js
export class CustomCode {
constructor() {}
run() {
console.log("CustomCode from the App running in the Library's worker!");
}
}
这里有一个 StackBlitz 运行示例,您可以使用。
如果我通过使用
vite build
构建生产版本来尝试相同的示例,然后使用 vite preview
为该生产版本提供服务,则会发生以下情况:
exports
。我认为它会做这两件事,因为在 Web Worker 的上下文中,您不会有任何导出。但有趣的是它在开发模式下仍然有效。
有人知道 Vite 是否有正确的方法吗?看起来 Web Worker API URL 功能距离我需要执行此操作仅 1 步。
可以在 Vite 中直接导入脚本作为 Worker。请参阅 https://vitejs.dev/guide/assets#importing-script-as-a-worker 和 https://vitejs.dev/guide/features#import-with-query-suffixes
// Separate chunk in the production build
import Worker from './shader.js?worker'
const worker = new Worker()
// sharedworker
import SharedWorker from './shader.js?sharedworker'
const sharedWorker = new SharedWorker()
// Inlined as base64 strings
import InlineWorker from './shader.js?worker&inline'
如果您需要字符串形式的 URL(因为像
pdfjs
这样的外部库在内部管理工作线程并且只需要 URL),您可以这样导入:
import MyWorker from './worker?worker&url'