Перейти к содержимому

32. Solid 2.0: что нового

Solid 2.0 — это не просто обновление, а переосмысление модели реактивности. Сохраняя обратную совместимость в синтаксисе, Solid 2.0 переписывает ядро: сигналы, эффекты, асинхронность и рендеринг работают по принципиально новым правилам.

Solid 2.0 ещё в разработке (alpha). Информация актуальна на момент написания статьи и может измениться.

В Solid 1.x сигнал — пара [getter, setter]. Значение читается вызовом функции:

// Solid 1.x
const [count, setCount] = createSignal(0);
console.log(count()); // вызываем как функцию

В Solid 2.0 сигналы имеют свойство .value — читать и писать можно напрямую:

// Solid 2.0 — новый API
import { signal } from 'solid-js';
const count = signal(0);
console.log(count.value); // читаем через .value
count.value = 5; // пишем через .value = ...
// Старый синтаксис () — по-прежнему работает для совместимости
console.log(count()); // ещё поддерживается

В Solid 1.x реактивность привязана к DOM-рендерингу. В Solid 2.0 — это автономная система, независимая от рендеринга:

// Solid 2.0: реактивность без компонентов
import { signal, effect, computed } from 'solid-js/universal';
// Работает в Node.js, Web Worker, CLI — без DOM!
const firstName = signal('Иван');
const lastName = signal('Петров');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
effect(() => {
console.log('Имя изменилось:', fullName.value);
});
firstName.value = 'Алексей'; // → 'Имя изменилось: Алексей Петров'

Solid 2.0 делает асинхронность первоклассной концепцией. Каждый сигнал может быть асинхронным:

// Solid 2.0: async сигналы
import { signal, asyncSignal } from 'solid-js';
// Сигнал с асинхронной инициализацией
const user = asyncSignal(async () => {
const res = await fetch('/api/user');
return res.json();
});
// Чтение возвращает Promise или значение
function Profile() {
return (
// Автоматически создаёт Suspense-граница
<p>{user.value.name}</p>
);
}

Solid 2.0 вводит компилируемые компоненты — JSX трансформируется в более оптимальный код:

// Solid 1.x JSX → компилируется в:
function Counter(props) {
const [count, setCount] = createSignal(0);
return createComponent(Button, {
get children() { return count(); },
onClick: () => setCount(c => c + 1)
});
}
// Solid 2.0 JSX → компилируется в оптимизированный вид:
function Counter(props) {
const count = signal(0);
// Компилятор создаёт точечные обновления без createComponent overhead
return /* compiled template */;
}

Solid 2.0 улучшает типизацию — signal() полностью выводит типы:

// Solid 1.x — нужны явные generic
const [items, setItems] = createSignal<string[]>([]);
// Solid 2.0 — тип выводится автоматически
const items = signal<string[]>([]);
items.value = ['один', 'два']; // TypeScript знает тип!
// Новые utility-типы
import type { Signal, ReadSignal, MaybeSignal } from 'solid-js';
// Signal<T> — сигнал с .value
// ReadSignal<T> — только для чтения
// MaybeSignal<T> — T | Signal<T> (для пропсов, которые могут быть сигналами)
function MyComponent(props: { count: MaybeSignal<number> }) {
// работает и с числом, и с сигналом!
}

SolidStart 2.0 построен поверх Vinxi и приносит кардинальные изменения:

// SolidStart 2.0: новые Server Functions
import { action, query } from '@solidjs/router';
// Server Query — кешируемый серверный запрос
const getUser = query(async (id: string) => {
'use server';
return db.users.findOne(id);
}, 'getUser');
// Server Action — мутация на сервере
const updateUser = action(async (data: FormData) => {
'use server';
await db.users.update(Object.fromEntries(data));
return redirect('/profile');
});
// Использование в компоненте
function ProfilePage() {
const user = createAsync(() => getUser(params.id));
return (
<form action={updateUser} method="post">
<input name="name" value={user()?.name} />
</form>
);
}
КонцепцияSolid 1.xSolid 2.0
Чтение сигналаcount()count.value (или count())
Запись сигналаsetCount(5)count.value = 5
ЭффектыcreateEffect(() => {...})effect(() => {...})
МемоcreateMemo(() => ...)computed(() => ...)
РеактивностьТолько в DOMУниверсальная
AsynccreateResourceasyncSignal, createAsync
РендерингcreateComponentКомпилируемые шаблоны

Solid 2.0 сохраняет обратную совместимость через codemods:

Окно терминала
# Автоматическая миграция
npx solid-codemod@latest migrate-to-v2 ./src
# Проверка deprecated API
npx solid-codemod@latest check ./src

Большинство компонентов продолжат работать без изменений — createSignal, createEffect никуда не денутся, просто появятся алиасы.

Сравнение концепций Solid 1.x и 2.0 в одном демо: