Vite:获取单独模块包的 URL,以便 Worker 可以动态导入它

问题描述 投票:0回答:1

问题

我正在创建一个主要在 Web Worker 中运行的库(尽管它也可以在主线程中运行)。我希望使用我的库的应用程序(假设他们使用 Vite 构建应用程序)能够创建与其主应用程序包分开的自定义代码包。应用程序应该能够以某种编程方式获取此自定义代码包的 URL,然后将其传递给 Web Worker(通过库 API)。然后,Web Worker 动态导入该包。

本质上,我需要一种好方法来允许应用程序将自定义代码注入到我的库的 Web Worker 中。是否有支持的方法可以通过 Vite 来实现这一点?

仅 Hacky 开发模式解决方案

我发现了一种有点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
为该生产版本提供服务,则会发生以下情况:

  1. Vite 从其捆绑包中的 CustomCodeModule 中删除了所有
    exports
  2. 由于bundle中没有导出任何内容,并且bundle中没有实际执行任何代码,因此Vite树完全摆脱了它。

我认为它会做这两件事,因为在 Web Worker 的上下文中,您不会有任何导出。但有趣的是它在开发模式下仍然有效。

有人知道 Vite 是否有正确的方法吗?看起来 Web Worker API URL 功能距离我需要执行此操作仅 1 步。

vite web-worker
1个回答
0
投票

可以在 Vite 中直接导入脚本作为 Worker。请参阅 https://vitejs.dev/guide/assets#importing-script-as-a-workerhttps://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'
© www.soinside.com 2019 - 2024. All rights reserved.