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

Deno 1.33: Deno 2 即将发布

正如最近在 Node Congress 2023 上的 “强制优化”演示 中提到的,我们正在努力在未来几个月内发布 Deno 2 的主要版本。虽然我们对 Deno 2 的愿景雄心勃勃,但我们从项目开始时的目标没有改变

轻松编码:无论是在移除配置、样板代码还是构建步骤方面,我们一直致力于让您轻松地深入代码并立即提高生产力。此版本使我们的 LSP 更加健壮,允许任何支持 LSP 的代码编辑器与 Deno 项目完美配合。

一流的性能:速度和效率对开发者和用户来说都很重要。此版本提高了 HTTP 和 WebSocket 服务器的性能,并为进一步的性能工作奠定了基础。

毫不妥协的安全。安全性是 Deno 的内置功能,采用的是选择性权限模型,因此您始终了解自己的代码可以访问什么。在接下来的几个月里,我们将为 Deno 的权限系统引入新功能,使其更轻松、更灵活地使用。

Deno 1.33 是朝着这些理想迈出的又一步。在这个版本中

随着我们接近 Deno 2,接下来的次要版本将专注于提高性能,创造一流的开发人员体验,增强安全性以及更强大的 Node/npm 兼容性。


内置 KV 数据库

Deno KV 是 Deno 中一个无缝集成的数据库。无需安装任何依赖项,您就可以立即开始构建应用程序。此外,当您部署到 Deno Deploy 时,您的数据将得到一致的、地理复制的全局数据库的支持。请记住,KV 目前是不可用的 API,因此您需要使用 –unstable 标志才能使用它。

立即开始使用 KV,无需任何设置

const kv = await Deno.openKv();

const key = ["users", crypto.randomUUID()];
const value = { name: "Alice" };
await kv.set(key, value);

const result = await kv.get(key);
result.value; // { name: "Alice" }

当然,数据在磁盘上既持久又耐用,确保即使在程序重启后也能可靠地存储和访问数据。

有关完整文档,请查看手册

更扁平的 deno.json 配置

deno.json 架构已扁平化,使其更易于阅读和写入。

"lint.files.exclude""fmt.options.lineWidth" 等嵌套选项现在可以在其各自部分的顶层使用。

不用再编写这样的代码

{
  "lint": {
    "files": {
      "exclude": ["gen.ts"]
    }
  },
  "fmt": {
    "options": {
      "lineWidth": 80
    }
  }
}

您现在可以编写这样的代码,效果相同

{
  "lint": {
    "exclude": ["gen.ts"]
  },
  "fmt": {
    "lineWidth": 80
  }
}

所有更改

之前 之后
bench.files.include bench.include
bench.files.exclude bench.exclude
fmt.files.include fmt.include
fmt.files.exclude fmt.exclude
fmt.options.useTabs fmt.useTabs
fmt.options.lineWidth fmt.lineWidth
fmt.options.indentWidth fmt.indentWidth
fmt.options.singleQuote fmt.singleQuote
fmt.options.proseWrap fmt.proseWrap
fmt.options.semiColons fmt.semiColons
lint.files.include lint.include
lint.files.exclude lint.exclude
test.files.include test.include
test.files.exclude test.exclude

此更改向后兼容,但我们将来会逐渐弃用旧的架构。

感谢 @scarf005 实施此更改。

减少了动态导入的权限检查

此版本在使用动态导入时带来了巨大的生活质量改进。

如果您在 import() 调用中使用字符串文字(例如 import("https://deno.land/std/version.ts")),Deno 将不再需要权限来执行此导入。我们很长时间以来一直能够下载和分析这些导入,经过讨论后,我们认为最好不要要求权限来执行此代码 - 它已经成为程序“模块图”的一部分,并在 deno info main.ts 的输出中显示出来。

此更改将使您更容易在某些情况下有条件地执行一些代码 - 例如,如果您有一个包含许多子命令的 CLI 工具,您可能希望仅在调用子命令时有条件地加载其相应的处理程序。这极大地改善了工具的启动时间。另一个示例是仅在需要时加载 polyfill,或仅在环境变量存在的情况下在服务器应用程序中执行调试代码。

请记住,对于不可静态分析的动态导入(即不使用字符串文字作为指定符的动态导入),仍然会检查权限。

import("" + "https://deno.land/std/version.ts");

import(`https://deno.land/std@${STD_VERSION}/version.ts`);

const someVariable = "./my_mod.ts";
import(someVariable);

感谢 Nayeem Rahman 实施此更改。

npm 和 Node 兼容性改进

node:cryptonode:httpnode:vm 模块自上次发布以来得到了极大的改进。我们为大多数 node:crypto API 提供了 polyfill,这解除了许多流行的 npm 包(包括云提供商 SDK)的障碍。对 node:httpnode:vm 的更改对于 Vite 用户来说尤其有用,现在 Vite 在与 Deno 一起使用时应该更加稳定和高效。

在此版本中实施的所有 API 的完整列表

  • crypto.checkPrime
  • crypto.checkPrimeSync
  • crypto.createSecretKey
  • crypto.createVerify
  • crypto.ECDH
  • crypto.generateKey
  • crypto.generateKeyPair
  • crypto.generateKeyPairSync
  • crypto.generateKeySync
  • crypto.generatePrime
  • crypto.generatePrimeSync
  • crypto.getCurves
  • crypto.hkdf
  • crypto.hkdfSync
  • crypto.sign
  • crypto.Sign
  • crypto.verify
  • crypto.Verify
  • crypto.X509Certificate
  • http.ClientRequest.setTimeout
  • http.IncomingMessage.socket
  • module.Module._preloadModules
  • vm.runInThisContext

在 npm 支持方面,我们极大地改进了 npm 包的缓存处理。从这个版本开始,Deno 会尽力从注册表中检索信息,当它遇到缓存中缺少的版本(或版本不匹配)的包时。这应该会导致更少的提示使用 --reload 标志来检索最新注册表信息的提示。

性能改进

在这个版本中,我们彻底改造了 HTTP 服务器的实现以及 WebSockets 的客户端和服务器端实现。在过去的几个月里,我们收到反馈,Deno.serveWebSocket API 并没有像预期的那样高效和可靠。

我们认真对待这些反馈,并一直在努力改进它们。虽然在 RPS 基准测试中的变化可能还没有在您的应用程序中显现出来,但我们采取了彻底的措施来改进这些 API 的整体性能,我们将在接下来的几个月里展示这些改进。

CLI 改进

deno bench - --no-run 标志

此版本新增了一个--no-run标志到deno bench子命令中,以便在不运行所有解析的基准文件的情况下缓存它们。这使得deno benchdeno test保持一致。

> deno bench --no-run
Download https://deno.land/[email protected]/path/mod.ts
Download ...etc...
Check file:///home/user/project/main_bench.ts

感谢Geert-Jan Zwiers 为此功能做出贡献。

deno task - unset 命令

deno task 中的 shell 中添加了一个跨平台的unset 命令,允许删除环境变量和 shell 变量。这与 POSIX unset 命令的工作方式相同,现在执行MY_VAR=会正确地将一个变量设置为为空。

{
  "tasks": {
    // `deno task example` outputs "1" then "false"
    "example": "export VAR=1 && echo $VAR && deno task next",
    "next": "unset VAR && deno eval 'console.log(Deno.env.has(\"VAR\"))'"
  }
}

LSP 文档预加载

在 Deno 的早期版本中,您可能会发现某些功能在您之前未打开文件的情况下无法正常工作。例如,对某些代码进行“查找引用”可能不会显示它在测试文件中被使用,除非测试文件之前已经被打开。现在,这个问题通过在初始化语言服务器时预加载文件来缓解,这应该可以带来更好的体验。

请注意,作为此预加载的一部分,语言服务器将遍历最多 1000 个文件系统条目,并在达到此限制时输出日志消息。如果您的工作区包含大量与 Deno 无关的文件,并且这成为了问题,您可能需要利用"deno.enablePaths"选项来部分启用工作区

Deno API 的更改

我们正在弃用Deno.run API。随着Deno.Command API 在 v1.31 中的稳定,它成为我们推荐的生成子进程的方式。Deno.run 有一些难以解决的怪癖,我们大部分精力都集中在设计更易于使用的更好 API 上。Deno.run 将在 v2.0 中删除,因此我们强烈建议您将代码迁移到Deno.Command

不稳定的Deno.serve API 在准备此 API 的稳定版本时,通过删除其中一个 API 重载,进行了重大更改。Deno.serve(handler: Deno.ServeHandler, options: Deno.ServeOptions) 重载已删除,在 v1.33 中不再可用。

请更新您的代码以使用任何可用的重载。

Deno.serve((_req) => new Response("Hello, world"));

Deno.serve({ port: 3000 }, (_req) => new Response("Hello, world"));

Deno.serve({
  onListen({ port, hostname }) {
    console.log(`Server started at http://${hostname}:${port}`);
    // ... more info specific to your server ..
  },
  handler: (_req) => new Response("Hello, world"),
});

我们计划在下个月稳定Deno.serve,它将成为比Deno.serveHttp更优选的 API。

标准库的更改

std/encoding 模块的重大更改

上一个发布文章中所宣布,以下 6 个编码模块已移至顶级。

  • std/encoding/csv 已移至 std/csv
  • std/encoding/yaml 已移至 std/yaml
  • std/encoding/toml 已移至 std/toml
  • std/encoding/json 已移至 std/json
  • std/encoding/jsonc 已移至 std/jsonc
  • std/encoding/front_matter 已移至 std/front_matter

在此版本中,这些已弃用的模块已完全删除。如果您尚未迁移到新的路径,请将您的导入说明符更新为它们。

注意:如果您不直接依赖这些已删除的路径,但您的传递依赖项错误地使用非版本化的模块 URL 依赖于这些路径,您可能无法通过更新您自己的源代码来修复问题。在这种情况下,请使用以下模式的导入映射

{
  "imports": {
    "https://deno.land/std/encoding/yaml.ts": "https://deno.land/[email protected]/encoding/yaml.ts"
  }
}

这将在您的整个依赖关系图中强制重新映射非版本化的标准库 URL(在本例中为https://deno.land/std/encoding/yaml.ts)到一个版本化的 URL(https://deno.land/[email protected]/encoding/yaml.ts),并将修复您的依赖项中的问题。

fs.exists 的弃用已取消

std/fs 模块中的existsexistsSync 曾于v0.111.0 中被弃用,但在本版本中已取消弃用。

这些 API 被弃用是因为它们的错误易发性。它们很容易导致称为TOCTOU 的竞争条件错误。然而,在弃用后,关于它们的正确/合理用法进行了长时间的讨论。在重新考虑了它们的便利性和易出错性之间的平衡后,决定恢复它们。

std/csv 模块的更新

在此版本中,添加了CsvStringifyStream API。此 API 将源流式输入转换为 csv 行流。

import { CsvStringifyStream } from "https://deno.land/[email protected]/csv/mod.ts";
import { readableStreamFromIterable } from "https://deno.land/[email protected]/streams/mod.ts";

const file = await Deno.open("data.csv", { create: true, write: true });
const readable = readableStreamFromIterable([
  { id: 1, name: "one" },
  { id: 2, name: "two" },
  { id: 3, name: "three" },
]);

await readable
  .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] }))
  .pipeThrough(new TextEncoderStream())
  .pipeTo(file.writable);

在上述添加之后,CsvStream 已被重命名为 CsvParseStream,以明确其用途。

感谢Yuki Tanaka 的贡献。

V8 11.4

此版本升级到最新版本的 V8 (11.4,之前是 11.2)。

此次升级提供了一些令人兴奋的 JavaScript 新功能