Vega и Vega-Lite в среде Node.js применяются как часть серверного графического пайплайна, где визуализация формируется без браузера и затем экспортируется в SVG, Canvas или статический HTML-фрагмент. Такой подход используется в генерации отчётов, серверных дашбордах, PDF-экспорте и аналитических системах, где клиентская отрисовка невозможна или нежелательна.
Серверная отрисовка в Vega строится вокруг трёх этапов:
Vega-Lite выступает декларативным DSL, который преобразуется в полноценную Vega-грамматику. Vega затем интерпретируется движком рендеринга.
Ключевой момент: Node.js не использует DOM, поэтому весь pipeline должен работать без браузерных API.
Базовые зависимости для серверного рендеринга:
npm install vega vega-lite vega-cli canvas
Дополнительно могут потребоваться:
npm install jsdom
npm install sharp
Назначение компонентов:
vega — runtime и View APIvega-lite — компилятор спецификацийcanvas — реализация HTMLCanvasElement для Node.jsjsdom — эмуляция DOM при необходимости сложных
интеграцийsharp — конвертация изображений (PNG, WebP, PDF
pipeline)Vega-Lite спецификация не может быть напрямую отрисована. Она компилируется в Vega JSON:
const vl = require('vega-lite');
const specLite = {
data: { values: [1, 2, 3, 4] },
mark: "bar",
encoding: {
x: { field: "value", type: "quantitative" },
y: { aggregate: "count", type: "quantitative" }
}
};
const compiledSpec = vl.compile(specLite).spec;
На этом этапе происходит:
После компиляции используется runtime:
const vega = require("vega");
const view = new vega.View(vega.parse(compiledSpec), {
renderer: "none",
logger: vega.logger(vega.Warn)
});
Режим renderer: "none" означает отсутствие DOM-рендера.
Дальнейший вывод осуществляется явно.
SVG — наиболее стабильный формат для серверной генерации:
view.toSVG()
.then(svg => {
require("fs").writeFileSync("chart.svg", svg);
})
.catch(err => console.error(err));
Особенности:
Для растрового вывода требуется node-canvas:
const { createCanvas } = require("canvas");
const canvas = createCanvas(800, 600);
view
.renderer("canvas")
.initialize(canvas)
.run()
.then(() => {
const buffer = canvas.toBuffer("image/png");
require("fs").writeFileSync("chart.png", buffer);
});
Ключевые аспекты:
Типовой серверный pipeline:
async function render(spec) {
const vega = require("vega");
const view = new vega.View(vega.parse(spec), {
renderer: "canvas"
});
await view.runAsync();
return view.toCanvas();
}
Этот вариант используется при:
SVG может быть встроен в HTML-шаблоны:
const svg = await view.toSVG();
const html = `
<html>
<body>
${svg}
</body>
</html>
`;
Такой подход применяется для:
Node.js позволяет динамически подгружать данные:
const data = JSON.parse(
require("fs").readFileSync("./data.json", "utf-8")
);
const spec = {
data: { values: data },
mark: "line",
encoding: {
x: { field: "date", type: "temporal" },
y: { field: "value", type: "quantitative" }
}
};
Поддерживаются источники:
Типовой серверный endpoint:
const express = require("express");
const vega = require("vega");
const vl = require("vega-lite");
const app = express();
app.get("/chart", async (req, res) => {
const spec = vl.compile({
data: { url: "data.json" },
mark: "bar",
encoding: {
x: { field: "category", type: "nominal" },
y: { field: "value", type: "quantitative" }
}
}).spec;
const view = new vega.View(vega.parse(spec), {
renderer: "canvas"
});
await view.runAsync();
const png = await view.toCanvas();
res.setHeader("Content-Type", "image/png");
png.createPNGStream().pipe(res);
});
app.listen(3000);
Серверная генерация графиков требует оптимизации:
Пример:
const specCache = new Map();
function getSpec(key, builder) {
if (!specCache.has(key)) {
specCache.set(key, builder());
}
return specCache.get(key);
}
Основные узкие места:
Оптимизационные подходы:
Vega не предназначена для рендеринга миллионов точек без агрегации.
Практики:
Пример агрегации:
transform: [
{ aggregate: [{ op: "mean", field: "value", as: "avg" }], groupby: ["category"] }
]
Важные ограничения:
Особенно критично при использовании пользовательских spec.
Canvas требует системных библиотек:
В Docker-окружении часто используется:
RUN apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev
Распространённый подход:
Это разделяет:
Серверный Vega pipeline применяется для:
Генерация визуализаций становится частью backend-слоя, а не UI-слоя.