我们添加 Edge 运行时到 Next.js SDK 的经验
Logto 的 Next.js SDK 现在支持 Edge 运行时。在这篇文章中,我们将分享我们的冒险,看看我们面临的困难,我们是如何克服它们的,以及我们在过程中学到的有趣的东西。
##简介
Edge 运行时已经成为技术景观中的一个热词,驱动着从 AWS Lambda@Edge 和 Cloudflare Workers 到 Vercel Edge 的平台中的动态、低延迟功能。强调其重要性,Vercel 最近将 "experimental-edge" 改为 "edge",在他们热门的 Next.js 框架中标志着对官方支持的变化。
对于我们在 Logto 的 Next.js SDK 获得了严肃关注,我们想,"为什么不添加 Edge 运行时的支持呢?" 所以,我们卷起袖子,直接跳进去。在这篇文章中,我们将分享我们的冒险,看看我们面临的困难,我们是如何克服它们的,以及我们在过程中学到的有趣的东西。
##为 Edge 运行时支持转换模块和依赖性
与 Edge 运行时工作带来了一些独特的挑战,主要是因为它不支持 Node.js 常用的所有模块和依赖项。我们在 crypto、lodash 和 iron-session 模块上遇到了这个问题,需要一些创新的解决办法。
Crypto
在 Node.js 环境中,crypto 模块 作为 OpenSSL 的加密功能的包装器。不幸的是,Edge 运行时不支持它。但别担心 - 大多数 Edge 运行时会对 Web Crypto API 进行支持。尽管有一些小的差异,但它是 crypto 模块的一个坚实的替代品。例如,要生成随机字节:
以及哈希值:
Lodash
对于许多开发者来说,Lodash 由于其实用性而倍受青睐,但 Edge 运行时并不喜欢它。我们的解决方案是?我们用原生 JavaScript 方法替换了 Lodash 功能,从而保持了代码的有效率和可读性。
虽然替换大多数 Lodash 功能 并不是一项巨大的任务,但它确实需要一些技巧。让我们看看我们是如何以我们自己的方式重新创建 "once" 的实用性的:
Iron Session
iron-session 模块的最新版本适应 Edge 运行时,所以我们只需要更新我们的版本。就那么简单!
##在 Edge 运行时中导航 "Response" 的复杂性
当我们将 SDK 适应 Edge 运行时时,我们面临的另一个挑战是处理 "Response" 对象的差异。下面是我们如何克服这些差异的:
###手动创建响应
与 Node.js 不同,Edge 运行时的请求并不带有一个附带的响应。这意味着我们必须通过调用 new Response()
来创建它,这是返回数据的一个例子:
###放弃 "withIronSessionApiRoute"
在 Edge 运行时中,Response.body
是一个只读的事务。这意味着我们不能在准备数据前初始化响应。因此,我们值得信赖的 "withIronSessionApiRoute"(以及其他中间件)不得不被弃用。
为了理解我们替换了什么,让我们先来解包一下 withIronSessionApiRoute
实际上做了些什么:
- 它查看了 cookie,构造了一个 session 对象,并将其绑定到
res
。 - 如果 session 发生了变化,它会自动将 "set-cookie" 表头添加到
res
。
那么,我们在新的 Edge 运行时环境中如何模拟这个功能呢?
- 读取:我们利用了现有的
getIronSession
函数。通过给它一个空的和假的response
,按需求检索到 session。这替代了req.session
中的 "get" 方法。 - 写入:我们预先准备了一个带有数据的
response
,然后在这个response
实例上使用getIronSession
来获取 session 对象。一旦我们手中有了这个对象,我们就可以按需修改 session 了。
###重定向
在 Edge 运行时中,我们需要手动添加一个 Location
表头到我们的响应中以进行重定向。
##一个插件,两个运行时
在这个旅程中,我们决定坚持使用一个插件来支持 Edge 和 Node.js 运行时。
###这就是为什么
我们考虑过为 Edge 创建一个单独的插件,但很快就意识到这是没有必要的。我们的大部分代码在这两个运行时之间都是共享的,只有少数几行需要调整。而且,跨两个运行时使用 SDK 基本上是相同的,所以维护一个统一的插件是最有意义的。
###我们做了些什么
我们决定扩展现有的插件,而不是重复劳动。我们在包的根目录中添加了一个 "edge" 文件夹,紧挨着旧的 "src" 文件夹。然后,我们更新了 package.json 文件,向 "exports" 添加了一个新的路径。这样,Edge 和 Node.js 的运行时就可以在同一个包中和谐地共存,几乎不需要麻烦。
##总结
你可以在这里 查看我们的 Next.js SDK edge 部分的全部源代码。
通过分享我们拥抱 Edge 运行时的旅程,我们希望能够激励和指导其他人探索类似的路径。请继续关注我们的 Next.js SDK 的更多更新。