简体中文
  • nextjs
  • sdk
  • edge

我们添加 Edge 运行时到 Next.js SDK 的经验

Logto 的 Next.js SDK 现在支持 Edge 运行时。在这篇文章中,我们将分享我们的冒险,看看我们面临的困难,我们是如何克服它们的,以及我们在过程中学到的有趣的东西。

Sijie
Sijie
Developer

##简介

Edge 运行时已经成为技术景观中的一个热词,驱动着从 AWS Lambda@EdgeCloudflare WorkersVercel 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 实际上做了些什么:

  1. 它查看了 cookie,构造了一个 session 对象,并将其绑定到 res
  2. 如果 session 发生了变化,它会自动将 "set-cookie" 表头添加到 res

那么,我们在新的 Edge 运行时环境中如何模拟这个功能呢?

  1. 读取:我们利用了现有的 getIronSession 函数。通过给它一个空的和假的 response,按需求检索到 session。这替代了 req.session 中的 "get" 方法。
  2. 写入:我们预先准备了一个带有数据的 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 的更多更新。