Lit SSR サーバーの使用方法
テンプレートのレンダリング
「テンプレートのレンダリング」へのパーマリンクサーバーレンダリングは、@lit-labs/ssr
パッケージで提供されるサーバー固有の render()
関数を使用して、Lit テンプレートをレンダリングすることから始まります。
render 関数のシグネチャは次のとおりです
render(value: unknown, renderInfo?: Partial<RenderInfo>): RenderResult
通常、value
は、次のような Lit テンプレート式によって生成される TemplateResult
です。
html`<h1>Hello</h1>`
テンプレートにはカスタム要素を含めることができます。カスタム要素がサーバーで定義されている場合、それらのテンプレートとともに、順にレンダリングされます。
import {render} from '@lit-labs/ssr';
import {html} from 'lit';
// Import `my-element` on the server to server render it.
import './my-element.js';
const result = render(html`
<h1>Hello SSR!</h1>
<my-element></my-element>
`);
単一の要素をレンダリングするには、その要素のみを含むテンプレートをレンダリングします。
import {html} from 'lit';
import './my-element.js';
const result = render(html`<my-element></my-element>`);
RenderResultsの処理
「RenderResultsの処理」へのパーマリンクrender()
は、文字列にストリーミングまたは連結できる値のイテラブルである RenderResult
を返します。
RenderResult
には、文字列、ネストされたレンダリング結果、または文字列またはレンダリング結果の Promise を含めることができます。すべてのレンダリング結果に Promise が含まれているわけではありません。Promise は、カスタム要素がデータのフェッチなどの非同期タスクを実行するときに発生する可能性があります。しかし、RenderResult
には Promise を含めることができるため、文字列または HTTP レスポンスに処理することは潜在的に非同期操作です。
RenderResult
には Promise を含めることができますが、それでも非同期イテラブルではなく、同期イテラブルです。これは、同期イテラブルが非同期イテラブルよりも高速であり、多くのサーバーレンダリングでは非同期レンダリングを必要とせず、非同期イテラブルのオーバーヘッドを支払うべきではないためです。
同期イテラブルで Promise を許可すると、一種のハイブリッド同期/非同期イテレーションプロトコルが作成されます。RenderResult
を使用する場合は、各値が Promise かイテラブルかどうかを確認し、必要に応じて待機または再帰する必要があります。
@lit-labs/ssr
には、これを行うための 3 つのユーティリティが含まれています
RenderResultReadable
collectResult()
collectResultSync()
RenderResultReadable
「RenderResultReadable」へのパーマリンク RenderResultReadable
は、RenderResult
から値を提供する Node Readable
ストリームの実装です。これは、Writable
ストリームにパイプしたり、Koa などの Web サーバーフレームワークに渡したりできます。
これは、ストリーミング HTTP サーバーまたはその他のストリームをサポートする API と統合する場合に、SSR 結果を処理する推奨方法です。
import {render} from '@lit-labs/ssr';
import {RenderResultReadable} from '@lit-labs/ssr/lib/render-result-readable.js';
import {html} from 'lit';
// Using Koa to stream
app.use(async (ctx) => {
const result = render(html`<my-element></my-element>`);
ctx.type = 'text/html';
ctx.body = new RenderResultReadable(result);
});
collectResult()
「collectResult()」へのパーマリンク collectResult(result: RenderResult): Promise<string>
collectResult()
は、RenderResult
を受け取り、それを文字列に結合する非同期関数です。Promise を待機し、ネストされたイテラブルに再帰します。
例
import {render} from '@lit-labs/ssr';
import {collectResult} from '@lit-labs/ssr/lib/render-result.js';
import {html} from 'lit';
const result = render(html`<my-element></my-element>`);
const contents = await collectResult(result);
collectResultSync()
「collectResultSync()」へのパーマリンク collectResultSync(result: RenderResult): Promise<string>
collectResultSync()
は、RenderResult
を受け取り、それを文字列に結合する同期関数です。ネストされたイテラブルに再帰しますが、Promise に遭遇するとスローします。
この関数は非同期レンダリングをサポートしていないため、非同期関数を待機できない場合にのみ使用することをお勧めします。
import {render} from '@lit-labs/ssr';
import {collectResultSync} from '@lit-labs/ssr/lib/render-result.js';
import {html} from 'lit';
const result = render(html`<my-element></my-element>`);
// Throws if `result` contains a Promise!
const contents = collectResultSync(result);
レンダリングオプション
「レンダリングオプション」へのパーマリンクrender()
の 2 番目の引数は、オプションと現在のレンダリング状態をコンポーネントとサブテンプレートに渡すために使用される RenderInfo
オブジェクトです。
呼び出し元が設定できる主なオプションは次のとおりです。
deferHydration
: トップレベルのカスタム要素に、要素が自動的にハイドレートしないことを知らせるdefer-hydration
属性を追加するかどうかを制御します。これはデフォルトでfalse
に設定されており、トップレベルの要素が自動的にハイドレートするように設定されています。elementRenderers
: カスタム要素のレンダリングに使用するElementRenderer
クラスの配列。デフォルトでは、Lit 要素をレンダリングするためのLitElementRenderer
が含まれています。カスタムのElementRenderer
インスタンスを含めるように設定したり(ドキュメントは後日公開)、カスタム要素のレンダリングを完全に無効にするために空の配列に設定したりできます。
VMモジュールまたはグローバルスコープでのSSRの実行
「VMモジュールまたはグローバルスコープでのSSRの実行」へのパーマリンクNode でカスタム要素をレンダリングするには、まずグローバルな customElements
API で定義および登録する必要があります。これはブラウザ専用の機能です。そのため、Lit が Node で実行されると、サーバーで Lit をレンダリングするために必要な最小限の DOM API のセットを自動的に使用し、customElements
グローバルを定義します。(エミュレートされた API のリストについては、DOM エミュレーションを参照してください。)
Lit SSR は、カスタム要素をサーバー側でレンダリングする 2 つの異なる方法を提供します。それは、グローバルスコープでレンダリングするか、VM モジュールを介してレンダリングすることです。VM モジュールは、V8 仮想マシンコンテキスト内でコードを実行できるようにする Node の vm.Module
API を利用します。2 つの方法は、主にカスタム要素のレジストリなどのグローバル状態がどのように共有されるかが異なります。
グローバルスコープでレンダリングする場合、単一の共有 customElements
レジストリが定義され、すべてのレンダリングリクエスト間で共有されます。また、コンポーネントコードが設定する可能性のある他のグローバル状態も共有されます。
VM モジュールでレンダリングすると、各レンダリングリクエストに、メインの Node プロセスとは別のグローバルを持つ独自のコンテキストを持たせることができます。customElements
レジストリはそのコンテキスト内でのみインストールされ、その他のグローバル状態もそのコンテキストに分離されます。VM モジュールは、Node の実験的な機能です。
グローバル | VMモジュール |
---|---|
長所
| 長所
|
グローバルスコープ
「グローバルスコープ」へのパーマリンクグローバルスコープを使用する場合、テンプレートで render()
を呼び出すだけで、RenderResult
を取得してサーバーに渡すことができます。
import {render} from '@lit-labs/ssr';
import {RenderResultReadable} from '@lit-labs/ssr/lib/render-result-readable.js';
import {myTemplate} from './my-template.js';
// ...
// within a Koa middleware, for example
app.use(async (ctx) => {
const ssrResult = render(myTemplate(data));
ctx.type = 'text/html';
ctx.body = new RenderResultReadable(ssrResult);
});
VMモジュール
「VMモジュール」へのパーマリンクLit は、アプリケーションコードを別の VM コンテキストにロードし、独自のグローバルオブジェクトでレンダリングする方法も提供します。
// render-template.js
import {render} from '@lit-labs/ssr';
import {myTemplate} from './my-template.js';
export const renderTemplate = (someData) => {
return render(myTemplate(someData));
};
// server.js
import {ModuleLoader} from '@lit-labs/ssr/lib/module-loader.js';
import {RenderResultReadable} from '@lit-labs/ssr/lib/render-result-readable.js';
// ...
// within a Koa middleware, for example
app.use(async (ctx) => {
const moduleLoader = new ModuleLoader();
const importResult = await moduleLoader.importModule(
'./render-template.js', // Module to load in VM context
import.meta.url // Referrer URL for module
);
const {renderTemplate} = importResult.module.namespace
as typeof import('./render-template.js')
const ssrResult = await renderTemplate({some: "data"});
ctx.type = 'text/html';
ctx.body = new RenderResultReadable(ssrResult);
});
// server.js
import {ModuleLoader} from '@lit-labs/ssr/lib/module-loader.js';
import {RenderResultReadable} from '@lit-labs/ssr/lib/render-result-readable.js';
// ...
// within a Koa middleware, for example
app.use(async (ctx) => {
const moduleLoader = new ModuleLoader();
const importResult = await moduleLoader.importModule(
'./render-template.js', // Module to load in VM context
import.meta.url // Referrer URL for module
);
const {renderTemplate} = importResult.module.namespace;
const ssrResult = await renderTemplate({some: "data"});
ctx.type = 'text/html';
ctx.body = new RenderResultReadable(ssrResult);
});
注意: この機能を使用するには、Node 14+ が必要であり、モジュール互換の VM コンテキストを作成するために実験的な VM モジュールを使用しているため、--experimental-vm-modules
フラグを Node に渡す必要があります。