无服务器计算是软件开发领域的一个热门话题,这是有原因的。它承诺以一种更高效、更经济的方式来构建和运行可弹性扩展的应用程序。
Supabase是一个无服务器云平台,允许开发者在没有服务器的情况下构建复杂的网络和移动应用。Supabase最近推出了Edge Functions,作为那些寻求在其应用程序中添加无服务器功能的简单方法的人的一种选择。Edge Functions是用TypeScript编写的,可以用Supabase CLI分发和部署到29个地理区域,以覆盖全球用户。
在撰写本文时,Edge Functions在Supabase中仍是实验性的,很可能会有突破性的变化。不过,这一功能正在迅速受到开发者的欢迎,因为它是在没有大量服务器资源的情况下建立更强大功能的一种手段。
但是,Edge函数是如何工作的?还有,你如何编写无服务器代码?在这篇文章中,我们将介绍所有这些问题以及更多内容。
向前跳。
在进一步讨论之前,让我们先探讨一下Edge Functions是如何工作的,以及Supabase如何管理运行功能代码的平台。
了解Supabase的Edge Functions平台
Supabase的边缘功能是在安全的Deno环境中执行的。它们可以在几秒钟内部署到世界各地,而不需要使用Deno Deploy托管服务进行人工参与。这一切都由Supabase处理,因此你可以完全专注于你的应用程序的逻辑,而不必担心底层技术。
当Supabase边缘功能收到一个传入的请求时,该请求首先到达一个 "中继"。中继作为请求的API网关,对头文件中传递的JWT进行认证。它还提供一些额外的功能,如记录和速率限制。
在收到对某一功能的请求后,中继器会检索有关该功能的信息以及一个独特的标识符(称为部署ID),并将其传递给Deno Deploy平台。该平台安全地执行功能代码,并将响应传回中继站,然后由终端用户接收。
现在,让我们来创建和部署一个边缘功能样本。
开始使用
要开始使用Supabase Edge功能,你需要首先安装Supabase CLI并设置一个项目。请按照以下步骤操作。
- 安装Supabase CLI。
npm install -g supabase
- 使用命令登录到 CLI。
supabase login
- 用命令初始化 Supabase 项目。
supabase init
- 将您的本地项目链接到远程 Supabase 项目,像这样。
supabase link
--project-ref <your-project-ref>
创建边缘函数
要用 Supabase 创建一个新的边缘函数,请在你的项目中运行以下命令。
supabase functions new hello
这里,我们要创建一个叫做hello
的函数。
这将在你的Supabase文件夹内创建一个模板函数代码,地址是:。/functions/hello/index.ts
.
import { serve } from "https://deno.land/std@0.131.0/http/server.ts";
console.log("Hello from Functions!");
serve(async (req) => {
const { name } = await req.json();
const data = {
message: `Hello ${name}!`,
};
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" },
});
});
正如你在上面的区块中看到的,默认的函数代码相当简单,可以随时部署。serve
函数创建了一个 HTTP 服务器并开始监听传入的请求。
部署边缘函数
要用Supabase部署一个边缘函数,请运行以下命令。
supabase functions deploy hello
functions deploy
命令将打包你的函数代码并将其部署到远程 Supabase 项目。在Supabase仪表板中,在Invoke下,点击带有你的项目名称的URL(见下文),以找到更多细节。
你可以复制curl
请求,从终端测试你的函数。
在本地运行Edge函数
要在本地开发和运行Edge Function,你需要使用Docker在本地机器上设置Supabase。你可以查看本指南,了解在你的系统上设置Supabase的帮助。
通过运行以下命令启动Supabase项目。
supabase start
接下来,启动hello
功能,像这样。
supabase functions serve hello
该命令将为该函数启动一个本地服务器,并将监听本地主机端口54321。
要调用该函数,从你的终端发出一个curl
请求。
curl --request POST 'http://localhost:54321/functions/v1/hello' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
--header 'Content-Type: application/json' \
--data '{ "name":"Vijit" }'
Bearer
令牌在头中是需要的,用于认证。它可以是你的项目的ANON
密钥,SERVICE_ROLE
密钥,或用户的JWT令牌。
真实世界的用例
Supabase Edge Functions可以帮助你做的不仅仅是建立一个简单的CRUD应用;它们还可以让你连接到任何数据库,实时处理数据,甚至建立复杂的工作流。
让我们来看看一个实际的用例。我们将创建一个新的边缘函数,send-message
,它将使用Twilio Messaging API 发送一条短信。
要创建send-message
功能,运行以下命令。
supabase functions new send-message
你会发现默认的功能代码在/functions/send-message/index.ts
要使用Twilio Messaging API,你需要Twilio账户的SID密钥,一个授权令牌,以及一个将用于发送短信的虚拟号码。
在项目中创建一个.env
文件,并在文件中添加以下值。
// .env
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_PHONE_NUMBER=
注意,**一定不要在你的代码中暴露这些凭证,也不要把.env
文件添加到你的GitHub历史中。
接下来,定义一个接口来表示SMS的有效载荷。
// ./send-message/types/sms.interface.ts
export interface Sms {
[index: string]: string;
From: string;
To: string;
Body: string;
}
现在,创建一个辅助类TwilioSms
,使用Twilio Messaging API发送短信。这个类的构造函数将接受账户的SID和授权令牌。
SID和auth token是一起编码的,并将作为API请求中的授权头传递。
// ./send-message/helpers/twilio-sms.ts
import * as base64 from "https://denopkg.com/chiefbiiko/base64/mod.ts";
import { Sms } from "../types/sms.interface.ts";
export class TwilioSms {
private authorizationHeader: string;
constructor(private accountSID: string, authToken: string) {
this.authorizationHeader =
"Basic " +
base64.fromUint8Array(
new TextEncoder().encode(accountSID + ":" + authToken)
);
}
async sendSms(payload: Sms): Promise<any> {
const res = await fetch(
"https://api.twilio.com/2010-04-01/Accounts/" +
this.accountSID +
"/Messages.json",
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
Authorization: this.authorizationHeader,
},
body: new URLSearchParams(payload).toString(),
}
);
const data = await res.json();
return data;
}
}
在主函数处理程序中,你需要使用Deno.env.get()
方法加载环境变量,并从帮助器中导入TwilioSms
类。
接下来,使用sendSms()
方法向请求正文中指定的手机号码发送文本信息。
// ./send-message/index.ts
import { serve } from "https://deno.land/std@0.131.0/http/server.ts";
import { TwilioSms } from "./helpers/twilio-sms.ts";
const accountSid = Deno.env.get("TWILIO_ACCOUNT_SID") || "";
const authToken = Deno.env.get("TWILIO_AUTH_TOKEN") || "";
const fromMobile = Deno.env.get("TWILIO_PHONE_NUMBER") || "";
serve(async (req) => {
const { textMessage, toMobile } = await req.json();
const twilioClient = new TwilioSms(accountSid, authToken);
const message = await twilioClient.sendSms({
Body: textMessage,
From: fromMobile,
To: toMobile,
});
console.log({ message });
const data = {
isSuccess: false,
};
if (message.status === "queued") {
data.isSuccess = true;
}
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" },
});
});
为了在本地测试该函数,运行supabase functions serve
命令并在--env-file
参数中传递.env
文件路径,以便环境变量可以被函数访问。
supabase functions serve send-message --env-file ./supabase/.env
现在,使用curl
命令来调用该函数。
curl -i --location --request POST 'http://localhost:54321/functions/v1/' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
--header 'Content-Type: application/json' \
--data '{ "textMessage":"Hello Developer!", "toMobile": "+91XXXXXXXXXX" }'
要把你的本地环境变量推送到远程Supabase项目中,请运行supabase secrets set
命令。
supabase secrets set --env-file ./supabase/.env
一旦你的函数在本地测试完毕并准备好部署,请运行supabase functions deploy
命令。
supabase functions deploy send-message
限制
Supabase边缘函数提供了许多好处,但对于你能用这个新功能做什么,仍有一些限制。对于那些数据密集、执行起来可能很耗时的服务,你应该选择使用Supabase的数据库函数。
在撰写本文时,Edge Functions仍然是实验性的,在未来的更新中会有一些突破性的变化。目前,Edge Functions不能对端口25、465或587进行出站连接。另外,这个功能只支持POST请求,不支持HTML响应。最后,在本地开发中,一次只能提供一个边缘功能。
总结
Supabase边缘函数是扩展你的应用程序功能的一个伟大的解决方案。通过使用它们,你可以向你的应用程序添加一些通常需要单独的服务器端应用程序的功能。
在这篇文章中,我们研究了Supabase边缘函数的工作原理,并探讨了如何创建、部署和运行一个边缘函数。我们还介绍了一个真实的用例,即使用边缘函数在没有服务器的情况下发送一条短信。
如果你正在寻找一种方法来为你的应用程序添加自定义功能,而不需要自己管理基础设施,Supabase Edge Functions绝对值得一试。我希望这篇文章能帮助你开始使用Supabase和Edge Functions来构建你自己的应用程序。
The postUsing Edge Functions in Supabase:一篇完整的指南出现在LogRocket博客上。