ЧатиумРазработчикамСтоимость
Войти

Изоморфные страницы и компоненты

В веб-разработке существует концепция изоморфизма, которая заключается в том, что один и тот же код может выполняться как на сервере, так и на стороне клиента в браузере. Это позволяет разработчикам создавать приложения, которые работают одинаково эффективно в обеих средах, используя одни и те же технологии и инструменты разработки.

Преимущество изоморфизма заключается в том, что разработчикам не нужно писать отдельный код для серверной и клиентской частей приложения. Они могут использовать один и тот же код, который адаптируется к среде выполнения.

Компоненты, которые будут использоваться в браузере (изоморфные компоненты), должны быть помечены в файле первой строкой-комментарием: // @shared.

Если компонент помечен таким образом, его код можно отправить в браузер. Если пометки нет, код не отправляется в браузер.

// @shared

export function MyComponent(props: MyComponentProps) {
  const ref = nanoid() // идентификатор компонента

  return (
    <div>
      <MyComponentInitializer
        ctx={ctx} // контекст
        ref={ref} // идентификатор

        title={'one'} // свойства компонента
        subTitle={'two'}
      />
    </div>
  )
}

export const MyComponentInitializer = createClientInitializer(async ({ ctx, element, ...props }) => {
  // element = <div>
  // props.title
  // props.subtitle

  console.log('Этот код выполнится только на клиенте')
})

В одном файле определяется как тело компонента которое выполнится на сервере, так и код клиентской инициализации.

Поскольку компоненты имеют специальный инициализатор (createClientInitializer), для их корректной работы при динамическом добавлении или удалении на клиенте необходима специальная инициализация. Для этого существуют методы, аналогичные методам DOM для вставки элементов дерева, которые позволяют компонентам правильно инициализироваться.

Вспомогательные атрибуты style и script

Для тегов style и script можно использовать дополнительные атрибуты portal и portalDedupe.

portal может принимать значения: body-start, body-end, head-start, head-end. Указывает в какой тег перенести загрузку скрипта или стилей.

portalDedupe означает, что если такой скрипт или стиль уже добавлен, то второй раз добавлять не нужно.

Пример использования:

<link
  href="/my-component.css"
  rel="stylesheet"
  porta="head-end"
  portalDedupe
/>

Методы работы на клиенте

appendChild

Компонент добавляется как потомок как последний элемент. Это используется при создании нового элемента на клиенте.

await appendChild(
  element,
  <MyComponent
    ctx={ctx}
    title={'Второй заголовок'}
    subTitle={'Второй подзаголовок'}
  />
)

insertBefore

Компонент добавляется как потомок перед указанным элементом. Это используется при создании нового элемента на клиенте и отображении в определенном месте потомков.

await insertBefore(
  element,
  <MyComponent
    ctx={ctx}
    title={'Будет первым'}
    subTitle={'Подзаголовок'}
  />,
  firtstElement
)

replaceWith

Компонент заменяет элемент. Можно использовать при изменении компонента или для ререндера компонента целиком.

let componentElement = await replaceWith(
  componentElement,
  <MyComponent
    ctx={ctx}
    title={'Обновленный заголовок'}
    subTitle={'Обновленный подзаголовок'}
  />
)

toHtmlElement

Есть вспомогательная функция, которая подготавливает компонент и отдаёт его в виде DOM элемента для дальнейших действий с использованием стандартного SDK браузера.

Первым аргументом она принимает document.

const myComponentElement = await toHtmlElement(
  document,
  <MyComponent
    ctx={ctx}
    title={'Обновленный заголовок'}
    subTitle={'Обновленный подзаголовок'}
  />
)

document.body.appendChild(myComponentElement)