Типобезопасные composables для Web Worker'ов во Vue 3 — useWorker(), пул воркеров и реактивный useWorkerComputed(), с типами, выводимыми прямо из файла воркера.

Заметные фризы интерфейса от тяжёлых синхронных вычислений — сигнал, что пора вынести их в отдельный поток: vue-worker-kit даёт для этого готовые Vue-composables поверх Web Worker API.
Клиентская сортировка, фильтрация или парсинг большого набора данных выполняются в реальном системном потоке — интерфейс остаётся отзывчивым даже во время тяжёлого пересчёта.
Устаревший расчёт сам отменяется, а новый запускается в фоновом потоке чуть позже — пользователь печатает быстрее, чем считает воркер, но интерфейс не спотыкается.
Пул воркеров распределяет ресайз, конвертацию или превью сотен файлов по нескольким ядрам процессора, а большие бинарные данные передаются без копирования через transferables.
SharedWorker считает тяжёлое состояние один раз на все вкладки вместо того, чтобы каждая вкладка запускала расчёт заново — переключение между вкладками происходит мгновенно.

useWorker запускает тяжёлые синхронные задачи (сортировка, парсинг, обработка изображений) в настоящем системном потоке (Worker). Основной поток остаётся свободным для рендеринга и обработки событий — UI не тормозит даже при выполнении сложных расчётов, которые на главном потоке вызывали бы заметные фризы.

createWorkerPool создаёт пул воркеров, распределяя задачи между ними с ограничением параллелизма. Метод pool.map обрабатывает массивы данных конкурентно, сохраняя порядок результатов — это даёт реальное ускорение на многоядерных системах за счёт параллельного выполнения на нескольких CPU-ядрах одновременно, особенно эффективно для пакетной обработки изображений или расчётов.

useWorkerComputed работает как reactive computed, но все тяжёлые пересчёты выполняются внутри воркера. При изменении зависимостей (например, вводимого текста) старый вычисляемый запуск автоматически отменяется, а новый стартует с дебаунсом. Результат всегда актуален, при этом основной поток не блокируется даже при частых изменениях источника.

Типы входных и выходных данных выводятся автоматически из самого файла воркера через typeof import. Вам не нужно описывать их дважды — ни в воркере, ни на стороне вызова. Это даёт полную типобезопасность, автодополнение и проверку на этапе компиляции, не создавая лишнего связующего кода между главным потоком и воркером.

Передавайте большие бинарные данные (ArrayBuffer, OffscreenCanvas) без копирования через transferables. Получайте промежуточные результаты через стриминг (reportChunk) для прогрессивного рендеринга. Включайте LRU-кэширование для повторяющихся вычислений и автоматические ретраи с экспоненциальной задержкой для аварийно устойчивых операций. Встроенная DevTools-панель показывает состояние пула и задачи.

useSharedWorker подключает единственный SharedWorker для всех открытых вкладок сайта — тяжёлое состояние вычисляется один раз, а не в каждой вкладке заново. Метод warmup() заранее прогревает воркер, устраняя задержку первого запуска. Простаивающие воркеры сами останавливаются по таймауту, а onScopeDispose освобождает ресурсы при размонтировании.
Тяжёлая работа — сортировка большого массива — выполняется в отдельном потоке и не блокирует интерфейс, репортит прогресс и умеет прерваться по сигналу отмены.
import { defineWorkerHandler } from 'vue-worker-kit/worker'
export default defineWorkerHandler(async (data: number[], ctx) => {
for (let i = 0; i < data.length; i++) {
if (ctx.signal.aborted) throw ctx.signal.reason
if (i % 10_000 === 0) ctx.reportProgress(i / data.length)
}
return data.sort((a, b) => a - b)
})useWorker() создаёт воркер лениво и выводит тип результата прямо из обработчика — генерик-аннотация не нужна.
import { useWorker } from 'vue-worker-kit'
const { run, isRunning, progress, error, cancel } = useWorker<typeof import('./heavy-sort.worker')>(
() => new Worker(new URL('./heavy-sort.worker.ts', import.meta.url), { type: 'module' }),
)
const sorted = await run(hugeArray, { transfer: [hugeArray.buffer] })
// sorted: number[] — inferred from heavy-sort.worker.ts, no generic annotation needed С streaming: true воркер шлёт чанки по мере обработки через ctx.reportChunk() — chunks обновляется реактивно, пока итоговый результат ещё не готов.
import { useWorker } from 'vue-worker-kit'
const { run, chunks, isRunning } = useWorker<typeof import('./process.worker')>(
() => new Worker(new URL('./process.worker.ts', import.meta.url), { type: 'module' }),
{ streaming: true }, // required — without it `chunks` is undefined, not a ref
)
const finalResult = await run(largeDataset)
watch(chunks, (newChunks) => {
console.log('Received chunk:', newChunks.at(-1))
})
// Worker-side calls ctx.reportChunk(data) as it processes each batch —
// chunks.value fills in progressively while run() is still pending.