velund
v1.0.8
Published
Ядро согласованного рендеринга
Maintainers
Readme
Velund – Модульная UI-система на Vite для полиглотных бэкендов
🚀 Обзор
Velund — это не просто плагин для Vite, а интегрированная экосистема для создания кросс-платформенных UI-компонентов. Он позволяет фронтенд-разработчикам создавать компоненты с использованием привычных шаблонизаторов, а Velund компилирует их в готовые к использованию библиотеки, которые могут быть интегрированы и рендерены на любом бэкенде (Node.js, Python, PHP) через четко определенные API.
Velund фокусируется на:
- Контрактной разработке: Четкие схемы данных между фронтендом и бэкендом.
- Модульности: Возможность использовать готовые или создавать собственные рендереры и генераторы.
- Изоляции: UI-компоненты независимы от конкретной логики бэкенда.
- Автоматизации: Генерация библиотек и DTO для бэкенда.
✨ Основные возможности
- Агностик к шаблонизатору: Поддержка Twig (
@zebrains/velund-twig), Jinja/Nunjucks (@zebrains/velund-jinja), HTML (@velund/html). Система позволяет легко добавлять новые шаблонизаторы. - Типизированные компоненты: Строгое определение
propsиcontextкомпонентов с помощью схем TypeBox (транслируются в JSON Schema). - Backend-интеграция: Автоматическая генерация специализированных библиотек для бэкенд-языков (Node.js, Python, PHP), которые предоставляют готовый
Rendererкласс для рендеринга компонентов. - Горячая перезагрузка (HMR): Мгновенные обновления UI-компонентов в процессе разработки.
- Управление ассетами: Автоматическое управление путями к статическим ассетам, готовое к употреблению бэкендом.
- Асинхронные данные: Поддержка асинхронной подготовки данных (
prepareметод) для компонентов. - Расширяемая архитектура: Возможность использования готовых или создания собственных рендереров и генераторов благодаря API, предоставляемому
@velund/core.
📦 Установка
1. Создание нового проекта с create-velund (рекомендуется)
Используйте CLI-инструмент create-velund для быстрой инициализации проекта:
pnpm create velund
# или
npm create velund@latest
# или
yarn create velundcreate-velund интерактивно спросит вас о названии проекта, предпочитаемом шаблонизаторе и генераторе для бэкенда, и автоматически настроит vite.config.ts и установит необходимые зависимости.
2. Добавление Velund в существующий проект Vite
Установите velund и необходимые рендереры/генераторы:
pnpm add velund @zebrains/velund-twig # Для поддержки Twig-шаблонов
# и/или
pnpm add @velund/node # Для генерации Node.js-библиотеки
# и/или другие рендереры/генераторы🛠️ Базовая настройка vite.config.ts
// vite.config.ts
import { defineConfig } from 'vite';
import velund from 'velund'; // Основной плагин Velund
import twigRenderer from '@zebrains/velund-twig'; // Пример: рендерер для Twig
import phpGenerator from '@zebrains/velund-php'; // Пример: генератор для PHP
export default defineConfig({
plugins: [
velund({
// -- Основной шаблонизатор и генератор для проекта --
renderer: 'twig', // Указывает основной шаблонизатор (Twig, Jinja, HTML)
generator: 'php', // Указывает основной генератор для бэкенда (Node.js, Python, PHP)
// -- Регистрация рендереров --
// Все используемые рендереры должны быть зарегистрированы здесь.
// @velund/html уже встроен.
renderers: [
twigRenderer(), // Экземпляр Twig-рендерера
],
// -- Регистрация генераторов --
// Все используемые генераторы должны быть зарегистрированы здесь.
// @velund/node уже встроен.
generators: [
phpGenerator(), // Экземпляр Python-генератора
],
// -- Опции для интеграции с бэкендом --
assetsUrl: '/assets', // URL-путь по которому бэкенд должен отдавать статические ассеты Velund.
// Velund ожидает, что бэкенд будет обслуживать dist/assets по этому пути.
renderUrl: '/__render', // URL-путь для API-эндпоинта, который бэкенд должен предоставить.
// Используется в dev-режиме для рендеринга компонентов в рантайме.
// -- Прочие опции --
strictTemplateExtensions: false, // `true` если нужно строго проверять расширения файлов шаблонов (например, только .twig)
// nodeConfig?: VelundNodeGeneratorOptions; // Конфигурация для `@velund/node` генератора.
}),
],
});🧩 Определение UI-компонентов (.vel.ts)
Velund-компоненты определяются в виде TypeScript-файлов (обычно .vel.ts) и являются вашим основным способом создания UI. Вы можете автоматически собирать их через виртуальный модуль virtual:velund/components
// src/components/ProductCard.vel.ts
import { defineComponent } from 'velund/common'; // Хелпер для определения компонента
import { Type } from '@sinclair/typebox'; // Используется для описания схем данных
import template from './ProductCard.twig'; // Путь к файлу шаблона
export default defineComponent({
name: 'ProductCard', // Уникальное имя компонента
template, // Путь к связанному файлу шаблона (например, `.twig`, `.j2`, `.html`)
// -- Схема входных свойств (PropTypes) --
// `propsSchema` определяет данные, которые компонент принимает извне.
// Бэкенд-библиотека будет использовать эту схему для валидации входных данных.
propsSchema: Type.Object({
id: Type.Number(), // ID продукта
}),
// -- Схема контекста шаблона (ContextType) --
// `contextSchema` определяет структуру данных, которые будут доступны внутри шаблона.
// Это может быть объединение входных props и данных, полученных в `prepare` методе.
contextSchema: Type.Object({
title: Type.String(), // Название продукта
price: Type.Number(), // Цена продукта
description: Type.Optional(Type.String()), // Описание (необязательно)
}),
// -- Метод подготовки данных (Runtime Data Fetching) --
// `prepare` - асинхронная функция, которая вызывается для получения или подготовки данных для компонента.
// Она принимает `props` в соответствии с `propsSchema` и должна возвращать объект,
// который будет объединен с `props` и передан в шаблон в качестве `context`.
async prepare(props) {
// Пример: получить данные о продукте из API
const res = await fetch(`/api/products/${props.id}`); // Используется `fetch` (доступен в Node.js и браузере)
const productData = await res.json();
return productData; // Эти данные будут доступны в шаблоне как часть `context`
},
});🔌 Интеграция с бэкендом
Velund не просто генерирует JSON-схемы, он создает полноценные библиотеки для вашего бэкенд-языка.
Как это работает:
- Генерация библиотеки: При сборке вашего фронтенд-проекта (
npm run build), выбранныйgenerator(например,@velund/node) генерирует библиотеку в вашейbuild.outDir(например,dist/) директории. Rendererкласс: Эта сгенерированная библиотека предоставляет основной классRenderer(или аналогичный) и специализированные классы/функции для каждого вашего компонента (например,ProductCard).- API для бэкенда: Бэкенд-разработчик использует этот
Rendererкласс для:- Инициализации (обычно требуется указать путь к скомпилированным шаблонам).
- Регистрации
prepareметодов: Если компонент использует асинхронныйprepareметод (как в примере выше), бэкенд должен будет предоставить синхронную или асинхронную реализацию этого метода в своей среде. Сгенерированная типизация или описание для IDE поможет бэкенду понять, какие аргументы (props) должен принимать этот метод и какой контекст возвращать. - Рендеринга компонента: Вызов метода
render(componentName, context, meta?: boolean)предоставит готовый HTML.
Пример использования в Node.js (генерируемый @velund/node):
После сборки фронтенда, вы можете использовать сгенерированную библиотеку в вашем Node.js-проекте:
import express from 'express';
import path from 'path';
import {
HomePageComponent,
ProductPageComponent,
Renderer,
} from '../velund/lib';
const app = express();
const port = 3333;
// Предоставление директории с ассетами
const publicDir = path.join(process.cwd(), 'velund/assets');
app.use('/assets', express.static(publicDir));
// Регистрация prepare-метода дла компонента HomePage
HomePageComponent.registerPrepare(async () => {
const products = await (
await fetch('https://fakestoreapi.com/products')
).json();
products[0].title = Date.now() + products[0].title;
return {
products,
};
});
// Регистрация prepare-метода для компонента ProductPage
ProductPageComponent.registerPrepare(async ({ id }) => {
const product = await (
await fetch('https://fakestoreapi.com/products/' + id)
).json();
return product;
});
// Инициализация рендер-класса
const renderer = new Renderer();
// Регистрация роутов
app.get('/', async (req, res) => {
const html = await renderer.render('HomePage', {});
res.status(200).send(html).end();
});
app.get('/ProductPage', async (req, res) => {
const r = await renderer.render('ProductPage', req.query);
res.status(200).send(r).end();
});
app.listen(port, () => {
console.log(`🚀 Server running at http://localhost:${port}`);
});Важные нюансы для бэкенда:
- Сервировка ассетов: Бэкенд должен быть настроен на обслуживание статических файлов из директории Velund
dist/assetsпо пути, указанному вassetsUrl(/assetsпо умолчанию). - Runtime-рендеринг: Бэкенд может реализовать эндпоинт по пути
renderUrl(/__renderпо умолчанию) для динамического рендеринга компонентов в рантайме, используя логику, подобную той, что предоставляют генераторы. Это полезно для SSR или API-запросов.
⚙️ Детальная конфигурация плагина velund
Интерфейс iTwigPluginConfig (определен в src/types.ts) для функции velund():
| Опция | Тип | По умолчанию | Описание |
| -------------------------- | ----------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| renderer | string | 'html' | Обязательный. ID основного рендерера для проекта (например, 'twig', 'jinja', 'html'). Используется для выбора дефолтного рендерера. |
| generator | string | 'node' | Обязательный. ID основного генератора для проекта (например, 'node', 'python', 'php'). Указывает, какую бэкенд-библиотеку Velund должен генерировать. |
| assetsUrl | string | '/assets' | Путь URL, по которому бэкенд должен будет обслуживать статические ассеты (JS,CSS, изображения), сгенерированные Vite. Это критически важный контракт для бэкенда. |
| renderUrl | string | '/__render' | Путь URL для API-эндпоинта, который бэкенд должен будет предоставить для динамического рендеринга компонентов в рантайме. Velund использует этот же URL в режиме разработки для собственного отладочного сервера. |
| strictTemplateExtensions | boolean | false | Если true, Velund будет строго проверять, что расширения файлов шаблонов соответствуют зарегистрированным для рендереров (например, только .twig для Twig-рендерера). |
| generators | VelundGeneratorDescriptor[] | [] | Массив экземпляров генераторов, которые Velund должен использовать (например, [pythonGenerator(), phpGenerator()]). @velund/node встроен по умолчанию. |
| renderers | VelundRendererDescriptor[] | [] | Массив экземпляров рендереров, которые Velund должен использовать (например, [twigRenderer(), jinjaRenderer()]). @velund/html встроен по умолчанию. |
| nodeConfig | VelundNodeGeneratorOptions | {} | Конфигурация, специфичная для @velund/node генератора (если используется). |
📜 Лицензия
MIT © DNTZ
