使用 Deno 构建无服务器函数
为什么选择 Deno?
使用 Deno 可以立即提高您的生产力,让您开始构建无服务器函数。
- 无需配置您的工具链、项目和 TypeScript,因为 Deno 附带 现代开发工具链 和 原生 TypeScript 支持
- 使用您熟悉的 Web 平台 API,例如
fetch()
、压缩流、BroadcastChannel
、Web 工作者、WebSocket
等等。 - 使用 Deno 的选择性权限系统 降低供应链攻击的风险。
- 使用一行代码添加状态,使用 Deno KV,该功能内置于运行时。
无服务器函数
使用 Deno 构建无服务器函数就像创建一个接收请求并返回响应的 Web 服务器一样简单。
Deno.serve((req) => new Response("Hello world"));
在我们的手册中了解更多关于 Deno.serve()
的信息。
以下是一个更高级的无服务器函数示例,它根据一组查询字符串参数调整图像大小。
import {
ImageMagick,
initializeImageMagick,
MagickGeometry,
} from "https://deno.land/x/[email protected]/mod.ts";
import { parseMediaType } from "https://deno.land/[email protected]/media_types/parse_media_type.ts";
await initializeImageMagick();
function parseParams(reqUrl: URL) {
const image = reqUrl.searchParams.get("image");
if (image == null) {
return "Missing 'image' query parameter.";
}
const height = Number(reqUrl.searchParams.get("height")) || 0;
const width = Number(reqUrl.searchParams.get("width")) || 0;
if (height === 0 && width === 0) {
return "Missing non-zero 'height' or 'width' query parameter.";
}
if (height < 0 || width < 0) {
return "Negative height or width is not supported.";
}
const maxDimension = 2048;
if (height > maxDimension || width > maxDimension) {
return `Width and height cannot exceed ${maxDimension}.`;
}
const mode = reqUrl.searchParams.get("mode") || "resize";
if (mode !== "resize" && mode !== "crop") {
return "Mode not accepted: please use 'resize' or 'crop'.";
}
return {
image,
height,
width,
mode,
};
}
async function getRemoteImage(image: string) {
const sourceRes = await fetch(image);
if (!sourceRes.ok) {
return "Error retrieving image from URL.";
}
const mediaType = parseMediaType(sourceRes.headers.get("Content-Type")!)[0];
if (mediaType.split("/")[0] !== "image") {
return "URL is not image type.";
}
return {
buffer: new Uint8Array(await sourceRes.arrayBuffer()),
mediaType,
};
}
function modifyImage(
imageBuffer: Uint8Array,
params: { width: number; height: number; mode: "resize" | "crop" },
) {
const sizingData = new MagickGeometry(
params.width,
params.height,
);
sizingData.ignoreAspectRatio = params.height > 0 && params.width > 0;
return new Promise<Uint8Array>((resolve) => {
ImageMagick.read(imageBuffer, (image) => {
if (params.mode === "resize") {
image.resize(sizingData);
} else {
image.crop(sizingData);
}
image.write((data) => resolve(data));
});
});
}
Deno.serve(
async (req: Request) => {
const reqURL = new URL(req.url);
const params = parseParams(reqURL);
if (typeof params === "string") {
return new Response(params, { status: 400 });
}
const remoteImage = await getRemoteImage(params.image);
if (remoteImage === "string") {
return new Response(remoteImage, { status: 400 });
}
const modifiedImage = await modifyImage(remoteImage.buffer, params);
return new Response(modifiedImage, {
headers: {
"Content-Type": remoteImage.mediaType,
},
});
},
);
更复杂的无服务器函数可以
- 访问浏览器 API,例如地理位置
- 通过覆盖 HTTP 内容个性化用户体验
- 处理用户身份验证和会话请求
- 调整图像大小
- 动态生成 OG 和元图像
- 处理 Discord 或 Slack 机器人的请求
等等。
使用 Deno KV 添加状态
Deno KV 是一个全局复制的数据库,是为您的服务器添加状态最简单的方法。您不需要复制或粘贴环境变量,也不需要单独的步骤来配置数据库。您只需要一行代码。
const kv = await Deno.openKv();
您可以为您的无服务器函数添加状态,以便它们可以跨会话存储用户信息,从而解锁一整套新的用例和功能。
Node 怎么办?
在 Node.js 中,在为您的函数添加状态之前,您需要注册一个云数据库提供商,设置一个新的数据库,获取必要的 API 密钥和唯一地址,并将它们设置为环境变量。将您的无服务器函数部署到 Deno Deploy
Deno Deploy 是我们的无服务器边缘平台,它允许您在靠近用户的地方的边缘托管和运行您的函数。您的无服务器函数将具有高可用性和最小的网络延迟。
通过 连接 GitHub 帐户,在 Deno Deploy 上托管您的函数非常简单,而且免费。
您也可以 将您的 Deno 无服务器函数部署到 Cloudflare。
其他资源
以下是一些关于使用 Deno 构建无服务器函数的示例、博客文章和视频。