Использование сервера 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 содержит три утилиты, которые делают это за вас:
RenderResultReadablecollectResult()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.