首頁 >web前端 >css教學 >將Web組件與Next(或任何SSR框架)一起使用

將Web組件與Next(或任何SSR框架)一起使用

William Shakespeare
William Shakespeare原創
2025-03-10 11:57:15408瀏覽

Using Web Components With Next (or Any SSR Framework)

>我以前的文章探索了Shoelace,這是一個組件庫,提供了一套全面吸引人的,可訪問的UX組件,該組件使用Web組件構建。 該體系結構允許框架 - 不平衡的用法。雖然React的Web組件集成不是最佳的,但存在解決方法。

> Web組件的一個重大限制是他們目前缺乏服務器端渲染(SSR)支持。 聲明性的影子DOM(DSD)正在開發中,但是當前支持是有限的,需要服務器端修改。 Next.js在該領域的開發很有希望。 本文著重於使用當前技術(包括Next.js)在任何SSR框架中管理Web組件。

這種方法涉及手動步驟,並且對初始頁面負載有輕微的性能影響。我們將解決績效優化策略。 該解決方案並非沒有權衡。徹底的測試和分析至關重要。

>

挑戰:SSR和Web組件

為什麼Web組件不與SSR無縫集成?

諸如Next.js Process React代碼之類的框架,將組件轉換為普通HTML。 React組件樹在服務器上渲染,此HTML發送到客戶端瀏覽器。 與此HTML一起是加載React和組件代碼的標籤。 瀏覽器重新呈現組件樹,將其與服務器渲染的HTML匹配。 這個被稱為水合的過程激活效果,事件處理程序和狀態管理,使應用程序交互。

> Web組件使它複雜化。 當渲染像鞋帶的組件時:

React(或任何JavaScript框架)直接通過這些標籤。 渲染邏輯位於Web組件的代碼中(在這種情況下為Shoelace)。 此代碼執行的時間至關重要。 <sl-tab-group></sl-tab-group>>

通常,Web組件註冊是通過水合過程中的JavaScript導入的。 這意味著該組件要等到水合後才能正確渲染,從而導致未風格的內容(FOUC)閃爍。 雖然理論上可以添加佔位符標記,但它是不切實際的,尤其是在第三方庫中。
<sl-tab-group ref="{tabsRef}">
  <sl-tab panel="general" slot="nav">General</sl-tab>
  <sl-tab panel="custom" slot="nav">Custom</sl-tab>
  <sl-tab panel="advanced" slot="nav">Advanced</sl-tab>
  <sl-tab disabled panel="disabled" slot="nav">Disabled</sl-tab>
  <sl-tab-panel name="general">This is the general tab panel.</sl-tab-panel>
  <sl-tab-panel name="custom">This is the custom tab panel.</sl-tab-panel>
  <sl-tab-panel name="advanced">This is the advanced tab panel.</sl-tab-panel>
  <sl-tab-panel name="disabled">This is a disabled tab panel.</sl-tab-panel>
</sl-tab-group>
> hydration Web組件註冊

問題是Web組件註冊代碼的延遲執行直至水合。 我們的解決方案涉及較早地運行此代碼。 我們將自定義Web組件代碼,並在文檔的

中添加阻止腳本。 這通常是不希望的,因為它與SSR的目的相矛盾,但可以確保立即渲染。 緩存將減輕性能的影響。這不是理想的長期解決方案。 Future Next.js DSD支持可能會消除這一需求。

>實現詳細信息

完整的代碼可在此GitHub存儲庫中可用,並使用Vercel在此處部署。該應用程序將鞋帶組件與文本一起在水合後發生變化。 文本將更新為“水合”,而鞋帶組件從一開始就正確呈現。

自定義捆綁

首先,創建一個導入所有Web組件定義的JavaScript模塊。對於鞋帶:

<sl-tab-group ref="{tabsRef}">
  <sl-tab panel="general" slot="nav">General</sl-tab>
  <sl-tab panel="custom" slot="nav">Custom</sl-tab>
  <sl-tab panel="advanced" slot="nav">Advanced</sl-tab>
  <sl-tab disabled panel="disabled" slot="nav">Disabled</sl-tab>
  <sl-tab-panel name="general">This is the general tab panel.</sl-tab-panel>
  <sl-tab-panel name="custom">This is the custom tab panel.</sl-tab-panel>
  <sl-tab-panel name="advanced">This is the advanced tab panel.</sl-tab-panel>
  <sl-tab-panel name="disabled">This is a disabled tab panel.</sl-tab-panel>
</sl-tab-group>
這個模塊不能直接導入;必須定制捆綁,以防止納入常規的JavaScript束。 我將使用Vite。安裝它(

)並創建> npm i vite vite.config.js這將在

中創建一個捆綁包。 將其移至Next.js服務中的
import { setDefaultAnimation } from "@shoelace-style/shoelace/dist/utilities/animation-registry";

import "@shoelace-style/shoelace/dist/components/tab/tab.js";
import "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js";
import "@shoelace-style/shoelace/dist/components/tab-group/tab-group.js";

import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";

setDefaultAnimation("dialog.show", { /* ... */ });
setDefaultAnimation("dialog.hide", { /* ... */ });
>文件夾。 節點腳本管理此腳本並創建一個模塊導出捆綁文件名:

shoelace-dir和一個相應的NPM腳本:public

import { defineConfig } from "vite";
import path from "path";

export default defineConfig({
  build: {
    outDir: path.join(__dirname, "./shoelace-dir"),
    lib: {
      name: "shoelace",
      entry: "./src/shoelace-bundle.js",
      formats: ["umd"],
      fileName: () => "shoelace-bundle.js",
    },
    rollupOptions: {
      output: {
        entryFileNames: `[name]-[hash].js`,
      },
    },
  },
});
腳本加載

>在Next.js的
// ... (Node script to move the bundle and create a module with the bundle path) ...
中,導入捆綁路徑,然後將a

標籤添加到

>:

>:_document.js> <script></script> 這可以確保Web組件註冊在初始HTML渲染之前運行。

"bundle-shoelace": "vite build && node util/process-shoelace-bundle",
性能優化:緩存

>將緩存標頭添加到下一個。

這有效地利用瀏覽器緩存。

結論
// ... (_document.js with script tag added) ...

雖然此方法需要手動步驟,但它為Web組件和SSR的當前局限性提供了解決方法。 框架 - 不足的組件的好處和使用新框架更容易實驗的優勢超過了初始實現的複雜性。 Web組件SSR支持的未來改進可能會簡化此過程。

>

以上是將Web組件與Next(或任何SSR框架)一起使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn