作者:Andy Jiang, Luca Casonato, Kevin Whinnery 2023.09.06
Deno Deploy可以轻松构建和托管_任何_JavaScript 应用程序、函数或 API 服务器。使用 Deno 简单而强大的 API( Web 标准 API、 Node.js 内置程序以及转换为一流 JavaScript API 的基本云服务,例如Deno KV (目前处于公开测试版)),编程变得更快、更容易。您的应用程序在全球 35 个地区靠近您的用户运行,确保最小的延迟和高可用性。
今天,我们很高兴地宣布 Deno Deploy 现在原生支持通过说明符运行 npm 模块npm:。这意味着你现在可以使用 npm 模块在边缘托管 Node.js 应用程序,而无需构建步骤。
以下是在 Deno Deploy 上运行 Express 应用程序的示例:
// Import express and instantiate it
import express from "npm:express@4";
const app = express();
// Register a route
app.get("/", (req, res) => {
res.send("Hello World!");
});
// Run the server!
app.listen(3000);
Deno Deploy 是第一个基于隔离的无服务器平台,原生支持 Node.js 内置插件和 npm 模块。这为 JavaScript 开发人员打开了一个充满可能性的全新世界的大门——现在,甚至你的 Node.js 应用程序也可以以最小的延迟、高可用性和 即时部署进行全球托管。
导入和使用超过 200 万个 npm 模块与 Deno 的其余部分无缝集成:一流的 TypeScript 支持、 格式化程序、linter 和测试运行器等内置工具,以及 在 IDE 中提供丰富编辑器体验的Deno 语言服务器。
无需捆绑步骤
Deno 中的 NPM 和 Node 支持是原生的——没有发生转译、捆绑步骤或 polyfill 注入。Deno Deploy 原生理解 Node.js API,并且本质上知道如何加载和执行 NPM 模块。
这对您来说有两个主要好处:更好的开发人员体验和更好的兼容性。
我们对 Deno Deploy 的短反馈循环和即时部署感到自豪。这也扩展到了 npm 支持。您可以使用说明符进行本地开发npm: ,并通过我们的无缝 GitHub 集成部署到 Deno Deploy,git push只需几秒钟即可从实时站点转移到实际站点。
因为我们不会转译、捆绑和聚合您的代码或您导入的任何 npm 模块,所以没有像这样的步骤会引入问题。这意味着在本地运行的代码将在 Deno Deploy 上运行,反之亦然。
由于没有捆绑或源映射,如果出现任何问题,您的Deno Deploy 堆栈跟踪和日志会显示与您在本地看到的内容相匹配的文件名和行号——不再需要挖掘难以理解的缩小和捆绑代码。
示例和用例
以下是你可以在 Deno Deploy 上使用 npm 包构建的一些示例。
快速化
Fastify是在 Node.js 中构建 API 服务器和 Web 应用程序的流行解决方案。借助 Deno Deploy 上的 npm 说明符支持,它现在也可以在边缘运行的 Web 应用程序中使用。
// Import the framework and instantiate it
import Fastify from "npm:fastify@4";
const fastify = Fastify();
// Declare a route
fastify.get("/", async function handler(request, reply) {
return "Hello World!";
});
// Run the server!
await fastify.listen({ hostname: "localhost", port: 3000 });
Deno.serve + OpenAI
NPM 支持不仅限于 Web 框架。你可以通过从 NPM 导入包来使用它来启动任何现有的 Deno 应用程序。例如,你可以使用 OpenAI SDK通过最先进的 AI 补全功能来增强你的应用程序。
import OpenAI from "npm:openai@4";
const openai = new OpenAI({ apiKey: Deno.env.get("OPENAI_API_KEY") });
Deno.serve(async (req: Request) => {
const completion = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: "Tell me a programmer joke" }],
});
const joke = completion.choices[0].message.content;
return new Response(joke);
});
加密 API
加密和解密是 npm 上最受欢迎的模块类别之一。这是一个使用npm上顶级软件包crypto-js之一的示例。
import CryptoJS from "npm:crypto-js@4";
Deno.serve((_req: Request) => {
// Encrypt
const ciphertext = CryptoJS.AES.encrypt("my message", "secret key 123")
.toString();
// Decrypt
const bytes = CryptoJS.AES.decrypt(ciphertext, "secret key 123");
const originalText = bytes.toString(CryptoJS.enc.Utf8);
return new Response(originalText);
});
兼容性
Deno Deploy 支持所有 47 个 Node.js 内置模块,例如fs、path和http。您可以通过说明符直接导入它们node:,就像在 Node.js 中一样。
任何依赖于这些API的npm包都将在Deno Deploy上工作。例如,在内部使用http的aws-sdk包可以正常工作:
/** @jsx jsx */
/** @jsxFrag Fragment */
import { Hono } from "https://deno.land/x/hono@v3.5.8/mod.ts";
import { Fragment, jsx } from "https://deno.land/x/hono@v3.5.8/middleware.ts";
import { DynamoDBClient } from "npm:@aws-sdk/client-dynamodb@3";
import {
DynamoDBDocumentClient,
ExecuteStatementCommand,
} from "npm:@aws-sdk/lib-dynamodb";
import { fromEnv } from "npm:@aws-sdk/credential-providers@3";
// Init DynamoDB client
const client = new DynamoDBClient({
region: "us-east-2",
credentials: fromEnv(),
});
const docClient = DynamoDBDocumentClient.from(client);
// Init Hono app
const app = new Hono();
// List TODOs
app.get("/", async (c) => {
const command = new ExecuteStatementCommand({
Statement: "SELECT * FROM Todos WHERE complete = ?",
Parameters: [false],
ConsistentRead: true,
});
const response = await docClient.send(command);
console.log(response);
return c.html(
<html>
<body style={{ margin: "10px auto", maxWidth: "400px" }}>
<h1>TODOs</h1>
<form action="/" method="POST">
<input type="text" name="text" />
<button
type="submit"
style={{
display: "inline-block",
marginLeft: "5px",
}}
>
Add Item
</button>
</form>
{response.Items.map((item) => {
return (
<div style={{ margin: "5px 0" }}>
{item.text}
</div>
);
})}
</body>
</html>,
);
});
// Add a TODO item
app.post("/", async (c) => {
const body = await c.req.parseBody();
const command = new ExecuteStatementCommand({
Statement: `INSERT INTO Todos value {'text':?, 'complete':?}`,
Parameters: [body.text, false],
});
try {
const response = await docClient.send(command);
console.log(response);
} catch (e) {
console.error(e);
}
return c.redirect("/");
});
Deno.serve(app.fetch);
虽然目前我们的 Node.js 兼容性非常好,但仍有一些 Node.js API 不受支持,或者尚未与 Node.js 实现完全兼容。
还有一些 npm 包无法在 Deno Deploy 上运行。由于沙箱限制,任何依赖 NodeAPI(Node 的本机插件层)的包都无法与 Deno Deploy 这样的无服务器系统一起使用。同样的安全沙箱还会阻止某些 Node.js API 工作,例如 child_process和vm。
如果你在 Deno Deploy 上使用特定 npm 模块时遇到任何问题, 请在此处提出问题。
下一步是什么
借助 npm 支持和公测版的 Deno KV,您的 JavaScript 应用程序可以访问超过 200 万个模块并解锁更多功能,提供高效且直观的开发体验(例如通过一行代码连接到全球分布式数据库),并提供快速的全局部署流程,直接融入您的 git 工作流程。所有这一切同时为您的最终用户提供最小的延迟和高可用性。
我们正在努力添加重要的有用功能,以进一步简化构建和托管复杂的生产就绪应用程序。我们即将发布许多激动人心的公告,敬请期待!