Skip to content

Worker Kit

v0.2.5DX и надёжностьVue

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

Worker Kit
Начать знакомство →
npm install vue-worker-kit@latest
01 — Назначение

Когда это пригодится

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

Таблица на 100 тысяч строк фризит при каждой сортировке

Клиентская сортировка, фильтрация или парсинг большого набора данных выполняются в реальном системном потоке — интерфейс остаётся отзывчивым даже во время тяжёлого пересчёта.

Живой поиск пересчитывается на каждое нажатие клавиши

Устаревший расчёт сам отменяется, а новый запускается в фоновом потоке чуть позже — пользователь печатает быстрее, чем считает воркер, но интерфейс не спотыкается.

Массовая обработка файлов или изображений в браузере

Пул воркеров распределяет ресайз, конвертацию или превью сотен файлов по нескольким ядрам процессора, а большие бинарные данные передаются без копирования через transferables.

Один и тот же дашборд открыт в нескольких вкладках

SharedWorker считает тяжёлое состояние один раз на все вкладки вместо того, чтобы каждая вкладка запускала расчёт заново — переключение между вкладками происходит мгновенно.

02 — Фичи

Коротко о главном

Вынос вычислений в отдельный поток без блокировки UI

Вынос вычислений в отдельный поток без блокировки UI

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

Пул воркеров для параллельной обработки данных

Пул воркеров для параллельной обработки данных

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

Реактивные вычисления в фоне через useWorkerComputed

Реактивные вычисления в фоне через useWorkerComputed

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

Сквозная типизация без дублирования и ручных аннотаций

Сквозная типизация без дублирования и ручных аннотаций

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

Продвинутое управление: transferables, стриминг, кэш и ретраи

Продвинутое управление: transferables, стриминг, кэш и ретраи

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

Общий воркер между вкладками и прогрев

Общий воркер между вкладками и прогрев

useSharedWorker подключает единственный SharedWorker для всех открытых вкладок сайта — тяжёлое состояние вычисляется один раз, а не в каждой вкладке заново. Метод warmup() заранее прогревает воркер, устраняя задержку первого запуска. Простаивающие воркеры сами останавливаются по таймауту, а onScopeDispose освобождает ресурсы при размонтировании.

03 — Быстрый пример

Как это работает

Обработчик воркера

Тяжёлая работа — сортировка большого массива — выполняется в отдельном потоке и не блокирует интерфейс, репортит прогресс и умеет прерваться по сигналу отмены.

heavy-sort.worker.ts
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() создаёт воркер лениво и выводит тип результата прямо из обработчика — генерик-аннотация не нужна.

component.ts
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 обновляется реактивно, пока итоговый результат ещё не готов.

streaming.ts
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.