Изоморфный код (isomorphic code) — это код, который может выполняться как на клиенте, так и на сервере, обеспечивая единый интерфейс для рендеринга компонентов. В контексте SkateJS это позволяет создавать веб-компоненты, которые могут предварительно отрисовываться на сервере, улучшая производительность и SEO, при этом сохраняя динамическую интерактивность на клиенте.
SkateJS построен на основе веб-компонентов и реактивной модели данных. Ключевой особенностью является возможность регистрировать компоненты и рендерить их без непосредственного доступа к DOM. Это достигается через использование рендер-функций, которые принимают данные и возвращают виртуальные узлы (Virtual DOM).
import { define, h, Component } from 'skatejs';
class MyComponent extends Component {
static get props() {
return {
message: String
};
}
renderCallback() {
return <div>{this.props.message}</div>;
}
}
define(MyComponent);
В этом примере renderCallback возвращает JSX-узел,
который может быть использован как на сервере, так и на клиенте. На
сервере его можно преобразовать в HTML, а на клиенте — интегрировать в
реальный DOM.
Для серверного рендеринга компонента используется метод
renderToString или аналогичная функция, позволяющая
превратить виртуальный DOM в HTML-строку.
import { renderToString } from 'skatejs/ssr';
const html = renderToString(<my-component message="Привет, мир!" />);
console.log(html);
// <my-component message="Привет, мир!"><div>Привет, мир!</div></my-component>
Результат рендеринга включает тег компонента и внутреннее содержимое, что позволяет браузеру корректно инициализировать его при загрузке.
После загрузки HTML на клиенте SkateJS автоматически подхватывает серверный рендеринг и продолжает управление компонентами. Это достигается через авто-гидратацию, когда компоненты, уже присутствующие в DOM, получают свои свойства и события.
document.addEventListener('DOMContentLoaded', () => {
define(MyComponent); // Автоматически инициализирует компоненты в DOM
});
Таким образом, серверный HTML плавно переходит в полностью интерактивный клиентский компонент без повторной генерации DOM.
Особенность изоморфного подхода заключается в том, что состояние компонента должно быть сериализуемым и переносимым между сервером и клиентом. SkateJS использует props и реактивные свойства для синхронизации данных.
class Counter extends Component {
static get props() {
return {
count: Number
};
}
increment() {
this.props.count++;
}
renderCallback() {
return (
<div>
<span>{this.props.count}</span>
<button oncl ick={() => this.increment()}>Увеличить</button>
</div>
);
}
}
Для изоморфного кода важно передавать начальное состояние с сервера:
const initialState = { count: 10 };
const html = renderToString(<counter {...initialState} />);
На клиенте этот объект используется для гидратации:
const counterElement = document.querySelector('counter');
Object.assign(counterElement, initialState);
define(Counter);
renderCallback не должен зависеть от window
или document.Изоморфный код в SkateJS позволяет создавать высокопроизводительные и SEO-дружелюбные приложения, где один и тот же компонент служит и для рендеринга на сервере, и для интерактивного поведения на клиенте. Это делает архитектуру более единообразной, а поддержку компонентов — проще.