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 との作業は一部のユニークな課題を提示します。これは主に、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 ほどではありません。我々のワークアラウンドは何だったのでしょうか? Lodash 関数をネイティブの JavaScript メソッドと交換し、コードの効率性と可読性を保ちました。
ほとんどの 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
が実際に何を行うのかを解説しましょう:
- それはクッキーを覗き、セッションオブジェクトを構築し、それを
res
に紐付けます。 - セッションに変更があった場合、自動的に "set-cookie" ヘッダーを
res
に追加します。
それでは、我々が新しい Edge Runtime 環境でこの機能をどのようにエミュレートしたのかを見てみましょう。
- 読み込み:既存の
getIronSession
関数を利用しました。それに空で偽のresponse
を与えることで、必要に応じてセッションを取得する。これがreq.session
の "get" メソッドを置き換えました。 - 書き込み:我々は upfront に data 付きの
response
を準備し、このresponse
インスタンス上でgetIronSession
を使用してセッションオブジェクトを取得しました。このオブジェクトを手に入れたら、必要なときにセッションを改変することができました。
リダイレクト
Edge Runtime ではリダイレクトを行うために、我々は手動で Location
ヘッダーをレスポンスに追加
要しました。