Использование сервера Lit SSR¶
Этот пакет входит в семейство экспериментальных пакетов Lit Labs. Руководство по использованию программ Labs в производстве см. на странице Lit Labs.
Рендеринг шаблонов¶
Серверный рендеринг начинается с рендеринга шаблона Lit template с помощью специфической для сервера функции render()
, предоставляемой в пакете @lit-labs/ssr
.
Функция рендеринга имеет следующую сигнатуру:
1 |
|
Обычно value
- это TemplateResult
, созданный выражением шаблона Lit, например:
1 |
|
Шаблон может содержать пользовательские элементы. Если пользовательские элементы определены на сервере, они будут отображаться по очереди, вместе с их шаблонами.
1 2 3 4 5 6 7 8 |
|
Чтобы отобразить отдельный элемент, вы создаете шаблон, содержащий только этот элемент:
1 2 3 |
|
Работа с результатами рендеринга¶
render()
возвращает RenderResult
: итератор значений, которые могут быть переданы потоком или сведены в строку.
RenderResult
может содержать строки, вложенные результаты рендеринга или обещания строк или результатов рендеринга. Не все результаты рендеринга содержат Promises - они могут возникать, когда пользовательские элементы выполняют асинхронные задачи, например, получение данных. Но поскольку RenderResult
может содержать Promises, его обработка в строку или HTTP-ответ является потенциально асинхронной операцией.
Даже если RenderResult
может содержать Promises, он все равно является синхронизируемым итерируемым, а не асинхронизируемым итерируемым. Это связано с тем, что синхронизируемые итерабели быстрее, чем асинхронизируемые итерабели, и многие серверные рендеры не требуют асинхронного рендеринга и поэтому не должны нести накладные расходы на асинхронизируемый итерабель.
Разрешение Promises в синхронном итерабеле создает своего рода гибридный протокол синхронной/асинхронной итерации. При потреблении RenderResult
вы должны проверять каждое значение на предмет того, является ли оно Promise или итерируемым, и ждать или рекурсировать в зависимости от необходимости.
@lit-labs/ssr
содержит три утилиты, которые делают это за вас:
RenderResultReadable
collectResult()
collectResultSync()
RenderResultReadable
¶
RenderResultReadable
- это реализация потока Node Readable
, который предоставляет значения из RenderResult
. Его можно направить в поток Writable
или передать фреймворкам веб-серверов, таким как Koa.
Это предпочтительный способ обработки результатов SSR при интеграции с потоковым HTTP-сервером или другим API, поддерживающим потоки.
1 2 3 4 5 6 7 8 9 |
|
collectResult()
¶
collectResult(result: RenderResult): Promise<string>
collectResult()
- это async-функция, которая принимает RenderResult
и объединяет его в строку. Она ожидает Promises и выполняет рекурсию во вложенные итерационные таблицы.
Пример:
1 2 3 4 5 |
|
collectResultSync()
¶
collectResultSync(result: RenderResult): Promise<string>
collectResultSync()
- это функция синхронизации, которая принимает RenderResult
и объединяет его в строку. Она выполняет рекурсию во вложенных итерациях, но бросает исключение, когда встречает Promise.
Поскольку эта функция не поддерживает асинхронный рендеринг, рекомендуется использовать ее только в тех случаях, когда вы не можете ожидать асинхронных функций.
1 2 3 4 5 6 |
|
Опции рендера¶
Вторым аргументом render()
является объект RenderInfo
, который используется для передачи опций и текущего состояния рендеринга компонентам и подшаблонам.
Основными опциями, которые могут быть установлены вызывающим пользователем, являются:
deferHydration
: определяет, добавлять ли к пользовательским элементам верхнего уровня атрибутdefer-hydration
, сигнализирующий о том, что элементы не должны автоматически увлажняться. По умолчанию это значение равноfalse
, так что элементы верхнего уровня будут автоматически гидратироваться.ElementRenderers
: Массив классовElementRenderer
, используемых для рендеринга пользовательских элементов. По умолчанию он содержитLitElementRenderer
для рендеринга Lit-элементов. Его можно настроить на включение пользовательских экземпляровElementRenderer
(документация готовится), или установить пустой массив для полного отключения рендеринга пользовательских элементов.
Запуск SSR в модуле VM или в глобальной области видимости¶
Чтобы отрисовывать пользовательские элементы в Node, они должны быть сначала определены и зарегистрированы в глобальном API customElements
, что является функцией только для браузера. Поэтому, когда Lit запускается в Node, он автоматически использует набор минимальных DOM API, необходимых для рендеринга Lit на сервере, и определяет глобальный customElements
. (Список эмулируемых API см. в Эмуляция DOM).
Lit SSR предоставляет два различных способа рендеринга пользовательских элементов на стороне сервера: рендеринг в глобальной области или через VM-модули. VM-модули используют API Node vm.Module
, который позволяет выполнять код в контексте виртуальной машины V8. Эти два метода отличаются в первую очередь тем, как разделяется глобальное состояние, например, реестр пользовательских элементов.
При рендеринге в глобальной области видимости будет определен один общий реестр customElements
, который будет использоваться во всех запросах рендеринга, а также любое другое глобальное состояние, которое может быть установлено кодом вашего компонента.
Рендеринг с помощью модулей VM позволяет каждому запросу рендеринга иметь свой собственный контекст с отдельным глобалом от основного процесса Node. Реестр customElements
будет установлен только в этом контексте, и другие глобальные состояния также будут изолированы от этого контекста. Модули VM - это экспериментальная функция Node.
Global | VM Module |
---|---|
Плюсы: Прост в использовании. Можно напрямую импортировать модули компонентов и вызывать render() с помощью шаблоновМинусы: Пользовательские элементы регистрируются в общем реестре для разных запросов рендеринга. | Плюсы: Изолирует контексты от различных запросов рендеринга. Минусы: Менее интуитивное использование. Необходимо написать и указать файл модуля с функцией для вызова. Медленнее из-за необходимости повторной оценки графа модуля при каждом запросе. |
Глобальная область видимости¶
При использовании глобальной области видимости вы можете просто вызвать render()
с шаблоном, чтобы получить RenderResult
и передать его на сервер:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Модуль VM¶
Lit также предоставляет возможность загружать код приложения в отдельный VM-контекст с собственным глобальным объектом и осуществлять рендеринг из него.
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Для использования этой возможности требуется Node 14+ и передача флага --experimental-vm-modules
Node из-за использования экспериментальных модулей VM для создания совместимого с модулями контекста VM.