Lit SSR 伺服器用法
渲染範本
“渲染範本”的永久連結伺服器端渲染從使用 @lit-labs/ssr
套件中提供的伺服器特定 render()
函數渲染 Lit _範本_ 開始。
渲染函數的簽名是
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—當自訂元素執行非同步任務(例如提取資料)時,可能會發生這些情況—但由於 RenderResult
可以包含 Promise,因此將其處理成字串或 HTTP 回應_可能_是非同步操作。
即使 RenderResult
可以包含 Promise,它仍然是同步可迭代物件,而不是非同步可迭代物件。這是因為同步可迭代物件比非同步可迭代物件更快,而且許多伺服器渲染不需要非同步渲染,因此不應該支付非同步可迭代物件的額外負擔。
允許 Promise 出現在同步可迭代物件中會建立一種混合同步/非同步迭代協定。當使用 RenderResult
時,您必須檢查每個值,以查看它是否為 Promise 或可迭代物件,並視需要等待或遞迴。
@lit-labs/ssr
包含三個公用程式來為您執行此操作
RenderResultReadable
collectResult()
collectResultSync()
RenderResultReadable
“RenderResultReadable”的永久連結 RenderResultReadable
是 Node Readable
串流實作,提供來自 RenderResult
的值。這可以管道傳送到 Writable
串流,或傳遞至 Koa 等網路伺服器框架。
這是與串流 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()
的第二個參數是 RenderInfo
物件,用於將選項和目前渲染狀態傳遞至元件和子範本。
呼叫者可以設定的主要選項是
deferHydration
:控制是否將defer-hydration
屬性新增至最上層的自訂元素,以表示這些元素不應自動水合。預設值為false
,因此最上層的元素會_自動_水合。elementRenderers
:用於渲染自訂元素的ElementRenderer
類別陣列。預設情況下,這包含LitElementRenderer
以渲染 Lit 元素。它可以設定為包含自訂ElementRenderer
執行個體(文件即將推出),或設定為空陣列以完全停用自訂元素渲染。
在 VM 模組或全域範圍中執行 SSR
“在 VM 模組或全域範圍中執行 SSR”的永久連結為了在 Node 中渲染自訂元素,它們必須先定義並向全域 customElements
API 註冊,這是僅限於瀏覽器的功能。因此,當 Lit 在 Node 中執行時,它會自動使用一組必要的最小 DOM API 來在伺服器上渲染 Lit,並定義全域 customElements
。(如需模擬 API 的清單,請參閱DOM 模擬。)
Lit SSR 提供兩種不同的方式來渲染伺服器端的自訂元素:在全域範圍中渲染或透過VM 模組渲染。VM 模組利用 Node 的 vm.Module
API,它可以在 V8 虛擬機器內容中執行程式碼。這兩種方法的主要區別在於如何共用全域狀態,例如自訂元素註冊表。
當在全域範圍中渲染時,單一的共用 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 內容中,並從該內容渲染的方式,該 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);
});
注意:由於使用實驗性 VM 模組來建立與模組相容的 VM 內容,因此使用此功能需要 Node 14 以上版本,並將 --experimental-vm-modules
旗標傳遞至 Node。