繁體中文(香港)
  • nextjs
  • sdk
  • edge

我們在 Next.js SDK 中加入 Edge Runtime 的經驗

Logto 的 Next.js SDK 現在支援 Edge Runtime。本文章將分享我們的冒險旅程,看看我們面對的障礙、如何克服它們,以及在這過程中學到的酷炫知識。

Sijie
Sijie
Developer

Stop wasting weeks on user auth
Launch secure apps faster with Logto. Integrate user auth in minutes, and focus on your core product.
Get started
Product screenshot

介紹

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 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 的實際作用:

  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 的更多更新。