我們在 Next.js SDK 中加入 Edge Runtime 的經驗
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 Runtimes 提供了對 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 的更多更新。