繁體中文(台灣)
  • nextjs
  • sdk
  • edge

我們添加 Edge Runtime 到 Next.js SDK 的經驗

Logto 的 Next.js SDK 現已支援 Edge Runtime。在這篇文章中,我們將分享我們的歷程,看看我們面臨的挑戰、如何克服這些困難,以及過程中學到的有趣知識。

Sijie
Sijie
Developer

介紹

Edge Runtime 已成為科技領域的一個熱門詞,驅動著從 AWS Lambda@EdgeCloudflare WorkersVercel Edge 平台上的動態、低延遲功能。為了強調其重要性,Vercel 最近將 "experimental-edge" 更改為 "edge",這標誌著其在受歡迎的 Next.js 框架中的官方支持。

隨著我們的 Next.js SDK 取得顯著進展,我們在 Logto 想,「為什麼不增加 Edge Runtime 支持呢?」於是,我們挽起袖子,馬上開始行動。在這篇文章中,我們將分享我們的歷程,看看我們面臨的挑戰、如何克服這些困難,以及過程中學到的有趣知識。

為 Edge Runtime 支持轉換模組和依賴項

使用 Edge Runtime 帶來了一些獨特的挑戰,主要是因為它不支持 Node.js 中常用的所有模組和依賴項。我們遇到了 crypto、lodash 和 iron-session 模組的問題,需要一些創新的替代方案。

Crypto

在 Node.js 環境中,crypto 模組作為 OpenSSL 密碼學函數的包裝器。不幸的是,Edge Runtime 不支持它。但別擔心——大多數 Edge Runtime 都支持 Web Crypto API。儘管有些小差異,它是 crypto 模組的可靠替代。例如,要生成隨機字節:

和哈希運算:

Lodash

Lodash 是許多開發者偏愛的工具,但 Edge Runtime 不喜歡它。我們的解決方案?我們用原生的 JavaScript 方法替換了 Lodash 函數,使我們的代碼既高效又易讀。

雖然替換大多數 Lodash 函數並不是一項艱鉅的任務,但需要一些技巧。讓我們來看看我們如何以自己的方式重現 "once" 的功能:

Iron Session

iron-session 模組的最新版本對 Edge Runtime 友好,因此我們所要做的只是更新我們的版本。就是這麼簡單!

在 Edge Runtime 中導航 "Response" 的複雜性

另一個我們在為 Edge Runtime 調整 SDK 時遇到的挑戰是處理 "Response" 對象的不同之處。以下是我們克服這些差異的方法:

手動創建回應

與 Node.js 不同的是,Edge Runtime 中的請求並不自帶回應。這意味著我們必須通過調用 new Response() 來創建它,這是返回數據的一個例子:

放下 "withIronSessionApiRoute"

在 Edge Runtime 中,Response.body 是只讀的。這意味著我們無法在數據準備好之前初始化回應。因此,我們可靠的 "withIronSessionApiRoute"(以及其他中間件)必須被擱置。

要了解我們替代了什麼,首先讓我們解剖一下 withIronSessionApiRoute 實際上做了什麼:

  1. 它檢查 cookie,構建會話對象,並將其綁定到 res
  2. 如果會話有變化,會自動將 "set-cookie" 標頭附加到 res

那麼,我們如何在新的 Edge Runtime 環境中模仿這一功能呢?

  1. 讀取:我們利用現有的 getIronSession 函數。通過給它一個空的和假的 response,根據需要檢索會話。這取代了 req.session 中的 "get" 方法。
  2. 寫入:我們事先準備了一個包含數據的 response,然後在這個 response 實例上使用 getIronSession 來獲得會話對象。一旦我們掌握了這個對象,我們可以根據需要修改會話。

重定向

在 Edge Runtime 中,我們需要手動將 Location 標頭添加到我們的回應中。

一個包,兩個運行時

在我們的這段旅程中,我們決定堅持使用一個包來支持 Edge 和 Node.js 兩個運行時。

這就是為什麼

我們想過為 Edge 建立一個單獨的包,但很快意識到這是不必要的。我們的大部分代碼在兩個運行時之間是共享的,只有少數幾行需要調整。此外,使用 SDK 在兩個運行時之間幾乎是相同的,所以維持一個統一的包是最合理的。

我們這樣做了

我們並沒有重複努力,而是擴展了現有的包。我們在包的根目錄中添加了一個 "edge" 文件夾,與舊的 "src" 文件夾緊挨著。然後,我們更新了 package.json 文件,添加了一個新的 "exports" 路徑。這樣,Edge 和 Node.js 運行時可以在同一個包中和諧共存,並不需要太多麻煩。

結束語

你可以在這裡查看我們 Next.js SDK edge 部分的完整源代碼。

通過分享我們擁抱 Edge Runtime 的旅程,我們希望激勵並指導其他探索類似路徑的人。請關注我們的 Next.js SDK 的更多更新。