首頁  >  文章  >  web前端  >  伺服器操作已修復

伺服器操作已修復

Linda Hamilton
Linda Hamilton原創
2024-10-21 06:22:02743瀏覽

伺服器操作的出現是為了減少客戶端程式碼簡化需要與伺服器通訊的互動。這是一個優秀的解決方案,可以讓開發人員編寫更少的程式碼。然而,在其他框架中實施它存在一些不容忽視的挑戰。

在本文中,我們將討論這些問題以及如何在 Brisa 中找到解決方案。

為什麼需要伺服器操作?

要了解伺服器操作提供的內容,回顧過去與伺服器的通訊方式很有用。您可能習慣於每次與伺服器互動時執行以下操作:

  1. 捕捉瀏覽器事件(客戶端)
  2. 標準化與序列化資料(客戶端)
  3. 向伺服器發出請求(客戶端)
  4. 在端點 API 中處理請求 (伺服器)
  5. 回覆必要的資料(伺服器)
  6. 等待伺服器回應並處理(客戶端)
  7. 更新客戶端上的資料並呈現變更(客戶端)

這七個動作每次互動都會重複。例如,如果您的頁面有 10 個不同的交互,您將重複非常相似的代碼 10 次,僅更改請求類型、URL、發送的資料和客戶狀態等詳細資訊。

一個熟悉的例子是
一:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

在伺服器中:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});

增加客戶端包大小......以及開發人員的挫折感。

Server Actions have been fixed


沮喪的開發者

伺服器操作如何運作

伺服器操作這些操作封裝在遠端過程調用(RPC)中,它管理客戶端-伺服器通信,減少客戶端上的程式碼並將邏輯集中在伺服器上:

  1. 捕捉瀏覽器事件(RPC 用戶端)
  2. 標準化與序列化資料(RPC 用戶端)
  3. 向 RPC 伺服器發出請求 (RPC 用戶端)
  4. 使用資料在伺服器上執行操作(RPC 伺服器)
  5. 選項 1:
  • 從伺服器渲染並將串流傳送到客戶端(RPC 伺服器)
  • 處理流的區塊,以便更改可見(RPC 客戶端)
  1. 選項 2:
  • 回覆必要的資料並將屬性從伺服器儲存傳送到客戶端儲存(RPC 伺服器)
  • 使正在監聽更改的訊號對儲存中的變更做出反應(RPC 用戶端)

這裡的一切都是由 Brisa RPC 為您完成的。

Server Actions have been fixed


遠端過程呼叫

這將是來自伺服器元件的程式碼:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

在這裡,開發人員不編寫客戶端程式碼,因為它是伺服器元件。 onInput 事件在反跳後接收,由客戶端 RPC 處理,而伺服器 RPC 使用「操作訊號」來觸發已向該儲存屬性註冊訊號的 Web 元件。

如您所見,這顯著減少了伺服器程式碼,最重要的是,客戶端上的程式碼大小不會隨著每次互動而增加。 RPC 用戶端程式碼佔用固定的 2 KB,無論您有 10 個還是 1000 個這樣的互動。這意味著客戶端包大小增加 0 位元組,換句話說,不會增加。

Server Actions have been fixed


客戶端包大小為 0 位元組

此外,在需要重新渲染的情況下,這是在伺服器上完成的,並以HTML 流的形式返回,使用戶比傳統方式更早地看到更改,在傳統方式中,您必須在客戶端上完成此工作伺服器回應。

這樣:

  • 改善使用者體驗(使用者體驗
  • 改善開發體驗(DX)

Server Actions have been fixed


快樂的開發者

Brisa Server Actions 與其他框架之間的差異

1. 要捕捉的事件數量

在 React 等其他框架中,他們只關注 操作作為 form onSubmit 的一部分,而不是任何事件。

這是一個問題,因為有許多非表單事件也應該從伺服器元件處理,而無需添加客戶端程式碼。例如,輸入的onInput 用於執行自動建議onScroll 用於載入無限滾動onMouseOver 進行onMouseOver

進行

Server Actions have been fixedonMouseOver

進行
懸停

應用程式比預期更具互動性

Server Actions have been fixed

2. 對伺服器操作有更多的 HTML 控制
許多框架也將HTMX 庫視為伺服器操作的一個非常不同的替代方案,事實上,它帶來了非常好的想法,可以與伺服器操作結合起來,只需在HTML 中添加額外的屬性即可發揮更大的潛能。 RPC Client可以考慮,例如我們之前見過的debounceInput。還有其他 HTMX 想法,例如在發出請求時顯示旋轉器的指示器,或能夠處理 RPC 用戶端中的錯誤。

HTMX 想法

3. 關注點分離

當伺服器操作在 React 中引入時,出現了新的範式轉變,許多開發人員在使用它們時必須更改心理晶片。 我們希望使其
盡可能熟悉Web平台

,這樣,您就可以從伺服器擷取序列化事件並使用其屬性。唯一有點不同的事件是已經傳送了 FormData 並具有 e.formData 屬性的 onSubmit,不過,其餘的
<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
事件屬性

都是可互動的。這是一個範例重設表單 在此範例中,根本沒有客戶端程式碼,在伺服器操作期間,您可以使用CSS

使用指示器停用提交按鈕

,以便表單無法提交兩次,並且在伺服器上執行操作後的同一時間,使用e.formData 存取表單資料,然後使用事件的相同API 重設表單

在精神上,這與使用網路平台非常相似。唯一的區別是所有伺服器元件的所有事件都是伺服器操作。 這樣,就實現了真正的關注點分離,沒有必要

「用戶伺服器」或「使用客戶端」放入您的元件不再。

請記住一切都只在伺服器上運行。唯一的例外是在客戶端上運行的src/web-components資料夾,並且事件正常

Server Actions have been fixed


兩個不同的世界,但一致

4. 事件傳播

在 Brisa 中,伺服器操作在伺服器元件之間傳播,就好像它們是 DOM 事件一樣。也就是說,從一個Server Action中,你可以呼叫一個Server Component的prop的事件,然後執行父Server Component的Server Action,等等

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

在這種情況下,onAfterMyAction 事件在父元件上執行,並且可以在伺服器上執行操作。這對於在伺服器上執行影響多個伺服器元件的操作非常有用。

Server Actions have been fixed


傳播動作

4. 兩個世界之間的溝通

特別是在過去的幾周里,在 X(以前的 Twitter)上進行了多次討論之後,Web 元件變得有點不受歡迎。然而,作為HTML的一部分,它是與伺服器操作互動最佳方式,原因如下:

  1. 您可以從伺服器擷取任何Web 元件事件並產生客戶端-伺服器通訊。範例 。這非常強大,因為 Web 元件內的所有事件都只是客戶端邏輯,而沒有放置任何伺服器邏輯,只需在使用 Web 元件時從伺服器進行伺服器操作即可。
  2. HTTP 協定 可用於其設計目的,串流媒體中傳輸超文本 (HTML),因此如果在重新從伺服器操作渲染WebWeb 元件的任何屬性都會更新,RPC 用戶端的差異演算法使Web 元件無需太多努力即可更新。 Brisa 中的 Web 元件 屬性 是訊號,它們使 Web 元件的內部部分做出反應而無需重新渲染。這個過程在其他框架中變得非常複雜,使得 RPC 伺服器必須透過網路處理 JSON 或 JS,而不是 HTML,這使得串流的實作更加複雜。

在 Web Components 中使用屬性需要序列化,就像不使用 Web Components 將資料從伺服器傳輸到客戶端一樣,因此,使用兩者,無需管理額外的序列化

注意:如果您有興趣,我會在另一篇文章中解釋流式 HTML 並使用比較演算法對其進行處理。

Server Actions have been fixed


透過網路傳送的超文本

5.新概念:行動訊號

在 Brisa 中,我們加入了一個新概念,為伺服器操作提供更多功能,這個概念稱為 「操作訊號」。 「行動訊號」的想法是,您有2 個商店,一個位於伺服器,一個位於客戶端

為什麼是2家店?

預設伺服器儲存 僅在請求等級存在。且您可以共享客戶端不可見的資料。例如,您可以讓中間件設定使用者並有權存取任何伺服器元件中的敏感使用者資料。透過生活在請求級別,不同請求之間不可能發生衝突,因為每個請求都有其自己的存儲並且不存儲在任何數據庫中,當請求完成,預設消亡。

另一方面,在客戶端商店中,它是一個商店,每個屬性在消費時都是一個信號,也就是說,如果它已更新,正在偵聽該訊號的Web 元件會做出反應。

但是,「操作訊號」的新概念是我們可以將伺服器儲存的生命週期延長到請求之外。為此,需要使用以下程式碼:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

此transferToClient方法,將伺服器資料共用到客戶端儲存並轉換為訊號。透過這種方式,很多時候不需要從伺服器進行任何重新渲染,您可以簡單地透過伺服器操作對正在偵聽該訊號的 Web 元件的訊號做出反應。

這次商店轉移使伺服器商店的生命現在:

渲染初始伺服器元件→客戶端→伺服器操作→客戶端→伺服器操作...

因此它從僅在請求級別生存到永久生存,兼容頁面之間的導航。

Server Actions have been fixed


在兩個世界(伺服器/客戶端)之間共用資料

範例:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});

在此範例中,我們延長了錯誤儲存屬性的壽命,不是在客戶端上使用,而是在伺服器操作中重複使用,然後最終在伺服器操作的重新渲染中重複使用。在這種情況下,作為非敏感數據,沒有必要對其進行加密。此範例程式碼全部發生在伺服器上,甚至重新渲染,用戶將在伺服器上渲染後看到錯誤,其中伺服器RPC 將在流中發送HTML 區塊,客戶端RPC 將對其進行處理以進行比較並顯示向用戶反饋錯誤。

6. 僅加密敏感數據

如果在伺服器操作中使用了渲染級別存在的某個變量,則在安全級別,許多框架(如Next.js 14)所做的就是加密此資料以創建在以下位置使用的資料的快照渲染的時間。這或多或少沒問題,但是始終加密資料會產生相關的計算成本並且它並不總是敏感資料。

在 Brisa 中,為了解決這個問題,有不同的請求,在初始渲染中它有一個值,並且在伺服器操作中您可以捕獲它在此請求中具有的值。

<input
  debounceInput={300}
  onInput={async (e) => {
    // All this code only runs on the server
    const data = await search(e.target.value);
    store.set("query", data);
    store.transferToClient(["query"]);
  }}
/>

這在某些情況下很有用,但並不總是有用,例如,如果您執行 Math.random,初始渲染和伺服器操作執行之間肯定會有所不同。

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

這就是為什麼我們創建了「行動訊號」概念,以將資料伺服器儲存傳送到客戶端儲存 ,並且開發者可以隨意決定是否加密或不

有時,您可能希望傳輸初始渲染中已存在的數據,而不是從伺服器操作查詢資料庫,即使它需要關聯的加密。為此,您只需使用:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});

當你這樣做時:

<input
  debounceInput={300}
  onInput={async (e) => {
    // All this code only runs on the server
    const data = await search(e.target.value);
    store.set("query", data);
    store.transferToClient(["query"]);
  }}
/>

Web 元件(客戶端)內部總是會加密,但在伺服器上總是會解密。

注意:Brisa 使用 aes-256-cbc 進行加密,這是 OpenSSL 推薦的用於安全加密資訊的加密演算法組合。加密金鑰是在專案建置過程中產生的。

Server Actions have been fixed


在兩個世界(伺服器/客戶端)之間共用加密資料

結論

在 Brisa 中,雖然我們喜歡支援輕鬆編寫 Web 元件,但目標是能夠在沒有客戶端程式碼的情況下製作 SPA,並且僅在純客戶端互動或必須觸及 Web API 時才使用 Web 元件。這就是為什麼伺服器操作如此重要,因為它們允許與伺服器互動而無需編寫客戶端程式碼。

我們鼓勵您嘗試 Brisa,您只需在終端機中執行此命令:bun create brisa,或嘗試一些範例來看看它是如何工作的。

參考

  • 伺服器操作約定
  • 伺服器操作行為
  • 有伺服器操作的表單
  • 巢狀操作
  • 伺服器端驗證與錯誤處理
  • 反跳伺服器操作
  • 樂觀更新
  • 實際重新渲染
  • 使用伺服器操作導航到另一個頁面
  • 訪問 Cookie
  • 伺服器操作的安全性
  • 行動訊號
  • 傳輸敏感資料
  • 伺服器操作中的道具
  • 在反向代理程式中使用伺服器操作

以上是伺服器操作已修復的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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