WebGPU без боли и с 25 КБ в бандле — разбираемся с vgpu от Vercel Labs
Давно я не встречал WebGPU-библиотеку, у которой есть бюджет на размер бандла, да ещё и проверяемый в CI. А тут именно так: полный экран с эффектом укладывается в 25 КБ gzipped, и если кто-то раздует этот лимит — сборка падает. Разбираемся, что за проект и зачем он рядовому фронтендеру.
Что это вообще такое
vgpu — TypeScript-библиотека для WebGPU от vercel-labs. Авторы описывают её как модульную и кросс-рантаймовую: один и тот же код работает в браузере, в headless-режиме под Node (через Dawn) и в тестах с мок-адаптером, где реальная видеокарта не нужна.
На момент написания у проекта 932 звезды и 36 форков, лицензия MIT. Развивается активно, судя по коммитам. WebGPU как API уже поддержан в Chrome и Edge, поэтому тема перестала быть экзотикой.
Кому это пригодится? Тому, кто рисует шейдеры, делает визуализации данных, генеративную графику или хочет запускать вычисления на GPU. И особенно тому, кто устал от того, что WebGPU-код в браузере и в тестах — это два разных мира.
Главные фишки
Шейдеры как TypeScript-модули
Моя любимая часть. .wgsl-файлы импортируются как обычные модули, причём с типами:
import waveShader from "./wave.wgsl";
Импорты резолвятся на этапе сборки через типизированную рефлексию WGSL. Не нужен отдельный шаг кодогенерации, не надо вручную описывать binding'и и синхронизировать их с шейдером. Компилятор сам знает, какие имена, типы и раскладки буферов у вас в WGSL.
Есть и стандартная библиотека: пакет @vgpu/wgsl-std отдаёт готовые функции — шум, хеши, цвет, сэмплинг. Шейдер может экспортировать свои функции для других шейдеров, как в обычном коде:
import { hash2 } from "@vgpu/wgsl-std/hash";
export fn grain(uv: vec2f, time: f32) -> f32 {
return hash2(uv * time).x;
}
Для тех, кто писал шейдеры методом копипасты кусков GLSL между проектами, это выглядит как разумная эволюция.
Один контекст вместо глобального состояния
init() возвращает единственный объект Gpu. Каждый вызов API — draw, effect, frame, surface — принимает его первым аргументом. Никакого скрытого глобального стейта.
Зачем это? Например, для тестов: хочется параллельно гонять несколько независимых GPU-контекстов, и с vgpu это просто ещё один вызов init(). А ещё такой стиль хорошо ложится на React strict mode и hot reload, где глобальные синглтоны регулярно ломают жизнь.
Быстрый пример из документации:
import { clock, init, effect, frameLoop, surface } from "vgpu";
import waveShader from "./wave.wgsl";
const gpu = await init();
const canvasSurface = surface(gpu, canvas, { dpr: [1, 2] });
const wave = effect(gpu, waveShader, { set: { speed: 2 } });
const time = clock(gpu);
frameLoop(gpu, (frame) => {
wave.set({ time: time.time });
frame.pass(canvasSurface, wave);
});
Обратите внимание на effect и set(): юниформы адресуются по именам из WGSL, а запись проходит сразу, без очередей. В цикле меняется только то, что реально изменилось.
Кросс-рантайм как базовая опция
Вот тут проект заметно отличается от конкурентов. Один публичный API, три рантайма:
- браузер — то, что ожидаемо;
vgpu/node— headless-режим на бэкенде Dawn, для рендера на сервере или в CLI;vgpu/mock— детерминированный мок-адаптер, с которым тесты не требуют GPU вообще.
Код в Node выглядит так:
import { draw, frame, init, target } from "vgpu/node";
import triangleShader from "./triangle.wgsl";
const gpu = await init();
const colorTarget = target(gpu, { size: [256, 256], format: "rgba8unorm" });
const triangle = draw(gpu, { shader: triangleShader });
frame(gpu, (f) => f.pass(colorTarget, triangle));
const pixels = await colorTarget.read();
gpu.dispose();
Смущает только одно: dispose() вызывается вручную. В браузере этого нет — там за вами убирает GC. Не критично, но помнить стоит.
Явные кадры вместо сцены-графа
frame(gpu, (f) => f.pass(target, effect)). Пассы, клиры и дроу-коллы — явные вызовы, никакого неявного состояния сцены. Кто имел дело с тяжеловесными 3D-фреймворками, оценит прозрачность: видно ровно то, что отправится на GPU.
Командная строка и агенты
Необычный поворот: проект явно рассчитан и на ИИ-агентов. Документация, галерея примеров и валидация шейдеров доступны прямо из CLI:
npx vgpu docs # офлайн-документация
npx vgpu examples # галерея примеров
npx vgpu check # валидация шейдеров
Сайт vgpu.sh отдаёт agents.md и llms.txt для LLM, есть read-only API и даже MCP-эндпоинт. Можно подключить агента через npx vgpu mcp.
Зачем обычному разработчику MCP в графической библиотеке? Смею предположить: запрос «напиши мне шейдер с raymarching» сейчас падает не на человека, а на Claude Code или Cursor. И у vercel-labs есть все основания позаботиться о том, чтобы агент сделал всё правильно.
Из чего состоит монорепозиторий
Проект собран как монорепозиторий с чётким разделением пакетов:
vgpu— основной API:init,draw,compute,effect,frame,bundle,target,uniforms;@vgpu/cli— командаvgpuс документами,checkиdoctor;@vgpu/core— низкоуровневые обёртки надDevice,Buffer,Texture, bind-группами;@vgpu/wgsl— превращает.wgslв JS-модули и резолвит импорты до бандлинга;@vgpu/wgsl-std— стандартная библиотека для WGSL;@vgpu/adapter-nodeи@vgpu/adapter-mock— адаптеры для Node и мока;@vgpu/render— вспомогательные утилиты за пределами основного рендеринга.
Хочется отдельно похвалить подход к размеру: неиспользуемые декларации вырезаются до минификации, а бюджет в 25 КБ на полный fullscreen-эффект проверяется в CI. Для сравнения: many WebGL-библиотеки с похожим функционалом весят на порядок больше.
Где это пригодится
Судя по описанию и API, целевые сценарии такие:
- Визуализация данных. Миллионы точек на GPU вместо долго рисующихся SVG-графиков.
- Генеративная графика и шейдерные эксперименты. Быстрый цикл: написал WGSL, импортировал, увидел результат.
- Рендер на сервере.
vgpu/nodeпозволяет генерить превьюшки и экспортировать кадры без браузера. - Тестирование графики. Мок-адаптер даёт детерминированный результат, CI не требует реальной видеокарты.
- Нейросети и GPU-тензоры. GitHub-описание упоминает их, хотя в README подробностей маловато.
Минусы, куда без них
Честно скажу: проект молодой. 932 звезды — это интересно, но не массовое признание; API ещё может поменяться. Документация есть (vgpu.sh + офлайн через CLI), но полных руководств по продакшену, вероятно, пока нет. Если планируете что-то серьёзное, закладывайте время на чтение исходников — благо, они открыты.
Ещё нюанс: WebGPU по-прежнему недоступен в Safari до определённых версий и в старых браузерах, так что для широкого продакшена с fallback на WebGL vgpu сам по себе проблему не решает.
Стоит ли пробовать
Если вы пишете на TypeScript и хотите начать с WebGPU — да, попробуйте. Порог входа низкий:
pnpm add vgpu
pnpm add -D @webgpu/types
Дальше — Getting started, а для тех, кто хочет сразу правильно, — гайд по производительности, где разобраны инстансинг, ping-pong, MSAA и другие приёмы.
Кому особенно зайдёт:
- фронтендерам, которым нужен GPU для визуализации или креативного кода;
- авторам библиотек, которым важно тестировать рендер без железа;
- тем, кто устал от магии тяжёлых 3D-фреймворков и хочет явного контроля;
- разработчикам, работающим в паре с ИИ-агентами.
Проект бесплатный, под MIT. Начните с галереи примеров на vgpu.sh — глазами это обычно убедительнее, чем словами.
