跳到主要内容
Deno 2 终于来了 🎉️
了解更多

使用 Deno 构建无服务器函数


为什么选择 Deno?

使用 Deno 可以立即提高您的生产力,让您开始构建无服务器函数。

无服务器函数

使用 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 上托管您的函数非常简单,而且免费。

了解为什么边缘是 Web 的未来.

您也可以 将您的 Deno 无服务器函数部署到 Cloudflare

其他资源

以下是一些关于使用 Deno 构建无服务器函数的示例、博客文章和视频。