為 Lit SSR 撰寫元件
Lit 在伺服器環境中渲染 Web 元件的方法對元件程式碼施加了一些限制,以實現高效的伺服器端渲染。撰寫元件時,請記住這些考量,以確保它們與 Lit SSR 相容。
注意:此頁面上列出的限制可能會隨著我們對 Lit SSR 的改進而變更。如果您希望看到支援特定的使用案例,請提交 issue 或開始討論串。
僅限瀏覽器程式碼
「僅限瀏覽器程式碼」的永久連結大多數瀏覽器 DOM API 在 Node 環境中不可用。Lit SSR 使用一個 DOM shim,它是渲染 Lit 模板和元件所需的最低限度。如需可用 API 的完整清單,請參閱 DOM 模擬頁面。
撰寫元件時,請從僅在客戶端而非伺服器端呼叫的生命週期方法執行命令式 DOM 操作。例如,如果您需要測量更新後的 DOM,請使用 updated()
。此回呼僅在瀏覽器上執行,因此可以安全地存取 DOM。
請參閱下方的生命週期章節,以取得在伺服器上呼叫的特定方法和僅限瀏覽器的方法清單。
某些定義 Lit 元件的模組也可能具有使用瀏覽器 API 的副作用(例如,偵測某些瀏覽器功能),導致該模組在非瀏覽器環境中匯入時中斷。在這種情況下,您可以將副作用程式碼移至僅限瀏覽器的生命週期回呼中,或進行條件化,使其僅在瀏覽器上執行。
對於簡單的情況,將條件式或可選鏈結新增至某些 DOM 存取可能足以防範不可用的 DOM API。例如
const hasConstructableStylesheets = typeof globalThis.CSSStyleSheet?.prototype.replaceSync === 'function';
lit
套件還提供了一個 isServer
環境檢查器,可用於編寫針對不同環境的條件式程式碼區塊
import {isServer} from 'lit';
if (isServer) {
// only runs in server environments like Node
} else {
// runs in the browser
}
條件式匯出
「條件式匯出」的永久連結對於更複雜的使用案例,請考慮使用 條件式匯出,它特別符合 "node"
環境,因此您可以根據模組是為了在 Node 中使用還是在瀏覽器中使用而使用不同的程式碼。使用者會根據是從 Node 還是瀏覽器匯入而取得套件的適當版本。熱門的打包工具(例如 rollup 和 webpack)也支援匯出條件,因此使用者可以為您的 bundle 引入適當的程式碼。
以下範例配置可能如下所示
// package.json
{
"name": "my-awesome-lit-components",
"exports": {
"./button.js": {
"node": "./button-node.js",
"default": "./button.js"
}
}
}
Node 進入點檔案可以手動建立,或者您可以使用打包工具來產生這些檔案。
打包工具
「打包工具」的永久連結如果可能,請避免將 Lit 内聯打包到已發布的元件中。
由於 Lit 套件使用條件式匯出為 Node 和瀏覽器環境提供不同的模組,我們強烈建議您不要將 lit
打包到發布到 NPM 的套件中。如果您這樣做,您的 bundle 將僅包含適用於您打包環境的 lit
模組,並且不會根據環境自動切換。
如果您使用 ESBuild 或 Rollup 等打包工具轉換您的程式碼,您可以將套件標記為外部,這樣它們就不會被打包到您的元件中。ESBuild 具有 packages
選項,可外部化所有依賴項,或者您可以在 external 選項中僅標記 lit
和相關套件。同樣地,Rollup 也有一個等效的 "external" 配置選項。
如果您必須將 Lit 函式庫程式碼打包到您的元件中(例如,透過 CDN 發布),我們建議建立兩個進入點:一個用於瀏覽器,另一個用於 Node。打包工具將具有選擇目標平台(如瀏覽器或 Node)的選項,或允許您明確指定用於解析模組的匯出條件。
例如,ESBuild 具有 platform
選項,在 Rollup 中,您可以將 "node"
提供給 @rollup/plugin-node-resolve
的 exportConditions
選項。
這些瀏覽器和 Node 目標的進入點必須在您的元件函式庫的 package.json
檔案中指定。請參閱 條件式匯出以取得更多詳細資訊。
生命週期
「生命週期」的永久連結伺服器端渲染期間僅執行某些生命週期回呼。這些回呼會產生元件的初始樣式和標記。其他生命週期方法會在元件水合後的水合期間以及執行期間在客戶端呼叫。
下表列出了標準自訂元素和 Lit 生命週期方法,以及它們是否在 SSR 期間被呼叫。所有生命週期在元素註冊和水合後都可在瀏覽器上使用。
在伺服器上呼叫的方法不應包含對未經過 shim 的瀏覽器/DOM API 的參考。未在伺服器端呼叫的方法可以包含這些參考,而不會導致中斷。
當 Lit SSR 是 Lit Labs 的一部分時,方法是否在伺服器上呼叫可能會變更。
標準自訂元素和 LitElement
「標準自訂元素和 LitElement」的永久連結方法 | 在伺服器上呼叫 | 備註 |
---|---|---|
constructor() | 是 ⚠️ | |
connectedCallback() | 否 | |
disconnectedCallback() | 否 | |
attributeChangedCallback() | 否 | |
adoptedCallback() | 否 | |
hasChanged() | 是 ⚠️ | 設定屬性時呼叫 |
shouldUpdate() | 否 | |
willUpdate() | 是 ⚠️ | 在 render() 之前呼叫 |
update() | 否 | |
render() | 是 ⚠️ | |
firstUpdate() | 否 | |
updated() | 否 |
ReactiveController
「ReactiveController」的永久連結方法 | 在伺服器上呼叫 | 備註 |
---|---|---|
constructor() | 是 ⚠️ | |
hostConnected() | 否 | |
hostDisconnected() | 否 | |
hostUpdate() | 否 | |
hostUpdated() | 否 |
Directive
「Directive」的永久連結方法 | 在伺服器上呼叫 | 備註 |
---|---|---|
constructor() | 是 ⚠️ | |
update() | 否 | |
render() | 是 ⚠️ | |
disconnected() | 否 | 僅限非同步指令 |
reconnected() | 否 | 僅限非同步指令 |
非同步性
「非同步性」的永久連結目前沒有機制可以等待非同步結果後再繼續渲染(例如來自非同步指令或控制器的結果),但我們正在考慮未來允許這樣做的選項。目前的解決方案是在伺服器上渲染頂層模板之前執行任何非同步工作,並將資料以某些屬性或屬性的形式提供給模板。
例如
- 非同步指令,例如
asyncAppend()
或asyncReplace()
,不會在伺服器端產生任何可渲染的結果。 until()
指令只會產生最高優先級的非 promise 佔位符值。
@lit-labs/testing
套件包含利用 Web Test Runner 外掛程式建立測試夾具的公用函式,這些測試夾具會使用 @lit-labs/ssr
在伺服器端渲染。它可以幫助測試您的元件是否可伺服器端渲染。請參閱 readme 中的更多資訊。