我們添加 Edge Runtime 到 Next.js SDK 的經驗
Logto 的 Next.js SDK 現已支援 Edge Runtime。在這篇文章中,我們將分享我們的歷程,看看我們面臨的挑戰、如何克服這些困難,以及過程中學到的有趣知識。
介紹
Edge Runtime 已成為科技領域的一個熱門詞,驅動著從 AWS Lambda@Edge 和 Cloudflare Workers 到 Vercel 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
實際上做了什麼:
- 它檢查 cookie,構建會話對象,並將其綁定到
res
。 - 如果會話有變化,會自動將 "set-cookie" 標頭附加到
res
。
那麼, 我們如何在新的 Edge Runtime 環境中模仿這一功能呢?
- 讀取:我們利用現有的
getIronSession
函數。通過給它一個空的和假的response
,根據需要檢索會話。這取代了req.session
中的 "get" 方法。 - 寫入:我們事先準備了一個包含數據的
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 的更多更新。