Начало работы: Waku
React Server Components: компоненты без функций в пропсах рендерятся прямо в серверных компонентах, интерактив — в файлах с 'use client'
1. Создайте приложение
Проверено с Waku 1.0.0-rc.3 (последний релиз — RC, стабильной 1.0 пока нет).
npm create waku@latest -- --project-name my-app
cd my-app
2. Установите пакет
Подходят react и react-dom 17, 18 и 19 (на React 17 id из useId появляются сразу после монтирования). Пакет — ES-модули (плюс CommonJS-копия для require()), без runtime-зависимостей, по файлу на модуль: в бандл попадают только импортированные компоненты, а как грузить и CSS только их — в разделе «Только нужный CSS» ниже. Шрифты — отдельные файлы: тема vercel (по умолчанию в ThemeProvider) использует Geist, поэтому рядом со стилями импортируйте valyro-ui/fonts/geist.css и valyro-ui/fonts/geist-mono.css, иначе текст будет системным шрифтом; glass использует системные шрифты, ей файлы не нужны. Пока пакет не опубликован, соберите и упакуйте его в репозитории (npm run build:core && npm pack ./dist/core) и установите tarball из корня репозитория: npm install /path/to/ValyroUI/valyro-ui-0.1.0.tgz.
npm install valyro-ui
3. Тема на <html>
Без _root.tsx Waku генерирует <html> сам и атрибутов темы в серверном HTML не будет. Создайте корневой элемент — первая отрисовка сразу в теме.
import type { ReactNode } from 'react';
export default async function RootElement({ children }: { children: ReactNode }) {
return (
<html lang="en" data-theme="glass" data-mode="light">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>{children}</body>
</html>
);
}
export const getConfig = async () => {
return {
render: 'static',
} as const;
};
4. Стили и ThemeProvider в layout
Layout — серверный компонент: ThemeProvider получает только строки, поэтому импортируется прямо здесь. Waku сам выводит CSS в <head>. Из шаблонного layout уберите обёртку со шрифтом Nunito (перебивает шрифт темы) и фиксированные Header/Footer; Tailwind из styles.css можно оставить — его preflight лежит в @layer base и стилям ValyroUI не мешает. При SSR задайте locale в ThemeProvider: иначе числа и даты форматируются по локали сервера, а в браузере — по локали пользователя, и гидрация падает на несовпадении текста («1,200» против «1 200»).
import '../styles.css';
import 'valyro-ui/styles.css';
import type { ReactNode } from 'react';
import { ThemeProvider } from 'valyro-ui';
type RootLayoutProps = { children: ReactNode };
export default async function RootLayout({ children }: RootLayoutProps) {
return (
<ThemeProvider theme="glass" mode="light" locale="en-US">
{children}
</ThemeProvider>
);
}
export const getConfig = async () => {
return {
render: 'static',
} as const;
};
5. Страница — серверный компонент
Пакет помечен 'use client', поэтому Card, Badge и другие компоненты с сериализуемыми пропсами рендерятся прямо из серверного компонента. Всё с обработчиками — в файле с 'use client': Showcase из гайда по Next.js лежит в src/components/Showcase.tsx без изменений. Функция в пропсе из серверного компонента (<Button onClick={…}>) роняет сборку: «Event handlers cannot be passed to Client Component props».
import { Badge, Card, CardContent, CardDescription, CardHeader, CardTitle } from 'valyro-ui';
import { Showcase } from '../components/Showcase';
// Server Component: ValyroUI components with serializable props render here directly;
// anything with handlers or state lives in the 'use client' Showcase.
export default async function HomePage() {
return (
<>
<title>ValyroUI on Waku</title>
<div style={{ padding: '32px 32px 0', maxWidth: 720 }}>
<Card>
<CardHeader>
<CardTitle>Server Component</CardTitle>
<CardDescription>Rendered on the server</CardDescription>
</CardHeader>
<CardContent>
<Badge color="green" dot>
RSC
</Badge>
</CardContent>
</Card>
</div>
<Showcase />
</>
);
}
export const getConfig = async () => {
return {
render: 'static',
} as const;
};
6. Соберите и запустите
npx tsc --noEmit
npm run build
npm run start