跳到主要内容
Deno 2.0 Release Candidate

Deno 2.0 候选版本

更新 2024/10/04: 我们发布了 Deno 2.0 候选版本的几个更新

多年来,我们一直在计划 Deno 的新主要版本。很多次,它似乎迫在眉睫,但我们意识到我们想要的功能需要更多的工作。现在,它终于要发生了。上个月,我们发布了最终的 1.x 版本 1.46,今天,我们正在为 Deno 2.0 推出候选版本,其中包含了我们期望在最终版本中包含的所有内容。这是自 1.0 以来最大的更新,其中包含诸如引入 Node 的 process 全局变量等重大更改。我们还做出了一些理念上的转变,例如,倾向于使用 deno install 而不是现在已弃用的 deno cache。请继续阅读以查看完整的更改列表,并分享您的反馈

要试用候选版本,请在您的终端中运行以下指令

deno upgrade
deno upgrade rc

ℹ️ 如果您使用的是 Homebrew 等替代分发方法,则 deno upgrade 可能不可用。

请按照 https://deno.org.cn 上的安装说明进行操作,然后运行上述命令。

Deno 2.0 候选版本的新特性

🚨️ 我们正在积极征求反馈 🚨️

此候选版本帮助我们在最终 2 版本发布之前识别问题。如果您遇到任何问题或需要额外的指导,请在 GitHub 中创建一个 issue 或在 我们的 Discord #deno-2-help 频道中提问。我们的团队正在积极监控这两个地方,并将尽快提供帮助。

全局变量的更改

Deno 2 带来了全局变量的两项重大更改——window 已被移除,Node 的 process 现在可用。


我们在 Deno v1.0 中引入了 window 全局变量,目标是使 Deno 尽可能与浏览器兼容。不幸的是,window 全局变量成为了用户的困扰之源。

许多库通过探测 window 全局变量而不是检查 DOM 的存在来检查它们是否在浏览器中执行。这导致了一类错误,这些错误发生在原本可以在 Deno 中工作的库中,原因是 window 是全局可用的。

Deno 开始在 v1.40 中不鼓励使用 window 全局变量,建议改用 globalThisself

// Deno v1.x
window.addEventListener("load", () => {
  console.log("loaded");
});

// Deno v2.x
globalThis.addEventListener("load", () => {
  console.log("loaded");
});

相比之下,process 全局变量已被广泛请求。

虽然长期以来可以通过从 node:process 模块导入 process 来使用它,但许多流行的框架都依赖于它在全局范围内的存在,通常在配置文件中使用。

尽管添加 import process from 'node:process'; 看起来很简单,但它经常给原本可以在 Deno 中无缝工作的流行框架的用户带来摩擦。

因此,随着 process 全局变量的添加,您可以期望更多最初为 Node.js 编写的代码无需在 Deno 中进行任何更改即可工作。但是,我们仍然鼓励用户首选显式导入。因此,添加了一个新的 no-process-global lint 规则,它将在您的编辑器中提供提示和快速修复,以使用导入语句代替。

依赖管理

Deno 2 带有几个新功能,可以改进依赖管理。

deno add 子命令现在可以处理带有子路径的说明符

# Before in Deno v1.46
deno add jsr:@std/testing/snapshot
error: Failed to parse package required: @std/testing/snapshot

Caused by:
    0: Invalid package requirement '@std/testing/snapshot'. Invalid version requirement. Invalid specifier version requirement. Unexpected character '/'
    ...

# Deno v2.0
deno add jsr:@std/testing/snapshot
Add jsr:@std/[email protected]

# Deno v1.46
deno add npm:preact/hooks
error: Failed to parse package required: npm:preact/hooks

Caused by:
    0: Invalid package requirement 'preact/hooks'. Packages in the format <scope>/<name> must start with an '@' symbol.
    1: Packages in the format <scope>/<name> must start with an '@' symbol.

# Deno v2.0
deno add npm:preact/hooks
Add npm:[email protected]

ℹ️ 现在需要使用 jsr:npm: 前缀来添加依赖项,以避免在两个注册表中使用相同名称的包时可能出现的歧义。

如果您省略前缀,Deno 将打印一个带有正确调用的建议,检查哪些注册表包含该包。

此外,如果您的项目包含 package.json 文件,Deno 将优先将 npm: 依赖项添加到 package.json 而不是 deno.json

cat package.json
{
  "dependencies": {}
}

deno add npm:express
Add npm:[email protected]

cat package.json
{
  "dependencies": { "express": "^5.0.0" }
}

您还可以使用 --dev 标志将“开发依赖项”添加到 package.json

deno add --dev npm:express
Add npm:[email protected]

cat package.json
{
  "devDependencies": { "express": "^5.0.0" }
}

deno install 现在支持 --entrypoint 标志,该标志允许您从给定的模块安装所有依赖项

// main.ts
import snapshot from "jsr:@std/testing/snapshot";
import express from "npm:express";
deno install --entrypoint main.ts
Download ...

添加了一个新的 deno remove 子命令,可以快速删除一些依赖项

deno add jsr:@std/testing
Added jsr:@std/[email protected]

cat deno.json
{
  "imports": { "@std/testing": "jsr:@std/testing@^1.0.2" }
}

deno remove @std/testing
Removed @std/testing

cat deno.json
{}

您还可以使用 deno remove 来处理 package.json 中列出的依赖项。


Deno 2 附带了一种新的、更简洁的锁文件格式 (v4),它将最大限度地减少更新依赖项时的差异,并确保可重现的构建。

cat deno.lock
{
  "version": "4",
  "specifiers": {
    "jsr:@std/assert@^1.0.4": "1.0.5",
    "jsr:@std/data-structures@^1.0.2": "1.0.4",
    "jsr:@std/fs@^1.0.3": "1.0.3",
    "jsr:@std/internal@^1.0.3": "1.0.3",
    "jsr:@std/path@^1.0.4": "1.0.6",
    "jsr:@std/testing@*": "1.0.2",
    "jsr:@std/testing@^1.0.2": "1.0.2"
  },
  // ...
}

Deno 将自动将您迁移到新的锁文件格式。


最后,Deno 改进了其错误消息传递,为常见问题提供了有用的提示,例如格式不正确的相对导入路径,或者在使用“裸说明符”时缺少依赖项

// main.ts
import "@std/dotenv/load";
deno run main.ts
error: Relative import path "@std/dotenv/load" not prefixed with / or ./ or ../
  hint: Try running `deno add jsr:@std/dotenv/load`
    at file:///main.ts:1:8

这些更新共同简化了 Deno 项目中管理依赖项的过程,使其更加直观并与现代开发工作流程保持一致。

权限系统更改

新的 Deno.errors.NotCapable 错误

Deno 的权限系统是其最受欢迎的功能之一。当程序尝试访问未使用 --allow-* 标志允许的 API 时,会引发错误。在 Deno v1.x 中,这是 Deno.errors.PermissionDenied

但这有一个问题。所有操作系统也会引发此错误,例如,当您的用户无权访问仅限管理员的文件时,或者当您尝试侦听特权端口时。因此,用户经常感到困惑,看到在使用了 --allow-all 标志的情况下仍然引发该错误。

在 Deno v2.0 中,缺少 Deno 权限现在会引发 Deno.errors.NotCapable 错误,以便更容易区分操作系统级别的错误和 Deno 错误。

await Deno.readTextFile("./README.md");

Deno v1.46

$ deno run main.ts
error: Uncaught (in promise) PermissionDenied: Requires read access to "./README.md", run again with the --allow-read flag
await Deno.readTextFile("./README.md")
           ^
    at Object.readTextFile (ext:deno_fs/30_fs.js:878:24)
    at file:///main.ts:1:12

Deno v2.0

$ deno run main.ts
error: Uncaught (in promise) NotCapable: Requires read access to "./README.md", run again with the --allow-read flag
await Deno.readTextFile("./README.md")
           ^
    at Object.readTextFile (ext:deno_fs/30_fs.js:777:24)
    at file:///main.ts:1:12

Deno.mainModule 不再需要 --allow-read 权限

Deno.mainModule API(它为您提供主模块的完整路径)的权限检查已放宽,不再需要完整的 --allow-read 权限。这也适用于 process.argv API。

此要求已弃用,但可以通过创建 Error 实例并检查其堆栈跟踪来获取主模块的路径。

--allow-hrtime 标志已移除

Deno v1.x 有一个 --allow-hrtime 标志,它会影响诸如 performance.now() 之类的 API,提供高分辨率计时。在 Deno 2 中,此标志已移除,这些 API 始终提供高分辨率计时。

此标志已被弃用,因为可以使用标准的 JavaScript API(如 WorkerSharedArrayBuffer)来实现高分辨率计时。

--allow-run 标志更改

--allow-run 标志有一些重大更改,旨在引导您更安全地执行子进程。

首先,如果您使用 --allow-run 标志但未指定二进制名称或二进制路径的允许列表,则会出现警告

new Deno.Command("echo", { args: ["hello"] }).spawn();
$ deno run --allow-run main.ts
Warning --allow-run without an allow list is susceptible to exploits. Prefer specifying an allow list (https://docs.deno.org.cn/runtime/fundamentals/security/#running-subprocesses)
hello

然后,每当使用 LD_*DYLD_* 环境变量生成子进程时,都需要完整的 --allow-run 权限。请注意,这些环境变量应很少被依赖。如果您确实需要使用它们,则应考虑通过运行额外的保护层(例如 Docker 容器)来进一步沙箱化 Deno。

new Deno.Command("echo", {
  env: {
    "LD_PRELOAD": "./libpreload.so",
  },
}).spawn();
$ deno run --allow-run=echo main.ts
error: Uncaught (in promise) NotCapable: Requires --allow-all permissions to spawn subprocess with LD_PRELOAD environment variable.
}).spawn();
   ^
    at spawnChildInner (ext:runtime/40_process.js:182:17)
    at spawnChild (ext:runtime/40_process.js:205:10)
    at Command.spawn (ext:runtime/40_process.js:479:12)
    at file:///main.ts:5:4

转义文件名中的逗号

现在可以授予读取和写入文件名中包含逗号的文件的权限。

在 Deno v1.x 中,逗号用于分隔多个文件名

deno run --allow-read=file1.txt,file2.txt
# grants permission to read `file1.txt` and `file2.txt`

这使得无法授予对名称中包含逗号的文件的权限。

在 Deno 2 中,可以通过用另一个逗号转义逗号来完成此操作

deno run --allow-read=file,,.txt,file2.txt
# grants permission to read `file,.txt` and `file2.txt`

API 更改

稳定版 API

Deno 2 中有几个 API 已稳定化

  • WebGPU API 不再需要 --unstable-webgpu 标志
  • Deno.dlopen() 和其他 FFI API 不再需要 --unstable-ffi 标志
  • Deno.createHttpClient() 不再需要 --unstable-http 标志

错误消息也得到了改进,当您尝试在没有相应标志的情况下使用不稳定的 API 时,会提供有用的提示

const db = await Deno.openKv();

Deno v1.46

$ deno run db.ts
error: Uncaught (in promise) TypeError: Deno.openKv is not a function
const db = await Deno.openKv();
                      ^
    at file:///db.ts:1:23

Deno v2.0

error: Uncaught (in promise) TypeError: Deno.openKv is not a function
const db = await Deno.openKv();
                      ^
    at file:///db.ts:1:23

    info: Deno.openKv() is an unstable API.
    hint: Run again with `--unstable-kv` flag to enable this API.

Deno API 的重大更改

ℹ️ 有关如何从已弃用的 API 迁移的更多信息,请访问 Deno 1 到 2 迁移指南

以下 API 已被移除

  • Deno.Buffer
  • Deno.close()
  • Deno.copy()
  • Deno.customInspect
  • Deno.fdatasync()Deno.fdatasyncSync()
  • Deno.File (此外,Deno.FsFile 不能再手动构造)
  • Deno.flock()Deno.flockSync()
  • Deno.fstat()Deno.fstatSync()
  • Deno.fsync()Deno.fsyncSync()
  • Deno.ftruncate()Deno.ftruncateSync()
  • Deno.funlock()Deno.funlockSync()
  • Deno.futime()Deno.futimeSync()
  • Deno.iter()Deno.iterSync()
  • Deno.metrics()
  • Deno.read()Deno.readSync()
  • Deno.readAll()Deno.readAllSync()
  • Deno.resources()
  • Deno.seek()Deno.seekSync()
  • Deno.shutdown()
  • Deno.write()Deno.writeSync()
  • Deno.writeAll()Deno.writeAllSync()

TLS 选项的处理已更新,不再支持以下选项

  • Deno.ConnectTlsOptions.certChain
  • Deno.ConnectTlsOptions.certFile
  • Deno.ConnectTlsOptions.privateKey
  • Deno.ListenTlsOptions.certChain
  • Deno.ListenTlsOptions.certFile
  • Deno.ListenTlsOptions.keyFile

以下接口已被移除

  • Deno.Closer
  • Deno.ReaderDeno.ReaderSync
  • Deno.SeekerDeno.SeekerSync
  • Deno.WriterDeno.WriterSync

此外,几个与 DNS 记录处理相关的接口已重命名

  • Deno.CAARecord to Deno.CaaRecord
  • Deno.MXRecord to Deno.MxRecord
  • Deno.NAPTRRecord to Deno.NaptrRecord
  • Deno.SOARecord to Deno.SoaRecord
  • Deno.SRVRecord to Deno.SrvRecord

“资源 ID”在以下 API 中不再可用

  • Deno.FsWatcher.prototype.rid
  • Deno.Conn.prototype.rid
  • Deno.TlsConn.prototype.rid
  • Deno.TcpConn.prototype.rid
  • Deno.UnixConn.prototype.rid
  • Deno.FsFile.prototype.rid
  • Deno.Listener.prototype.rid
  • Deno.TlsListener.prototype.rid

最后,一些 API 已被“软弃用”。这些 API 将继续工作,但将不再接收更新或错误修复。强烈建议并鼓励迁移到稳定的对应项

  • Deno.serveHttp() - 请改用 Deno.serve()
  • Deno.run() - 请改用 new Deno.Command()
  • Deno.isatty(Deno.stdin.rid) - 请改用 Deno.stdin.isTerminal()
  • Deno.isatty(Deno.stdout.rid) - 请改用 Deno.stdout.isTerminal()
  • Deno.isatty(Deno.stderr.rid) - 请改用 Deno.stderr.isTerminal()

命令行界面更改

Deno 2 移除对两个子命令的支持

  • deno bundle - 此子命令由于用户期望与内置捆绑器提供的实际功能不匹配,已在 Deno v1.31 中弃用

    许多 Deno 用户期望一个通用的、高度可定制的捆绑器。但是,Deno 的内置捆绑器旨在作为一个简单的工具,用于将多个文件连接成一个单文件,以便于分发;也没有任何设置来定制任何行为。

    我们计划实现一个新的内置捆绑器,因此请关注未来版本中的更新。

  • deno vendor - 已在 Deno v1.45 中弃用,并被使用 Deno v1.37 中引入的 deno.json 文件中的 vendor 选项的更简单解决方案所取代

几个 CLI 标志现在已弃用

  • --lock-write - 请改用 --frozen
  • --unstable - 请改用细粒度的 --unstable-<feature> 标志
  • test --allow-none - 请使用 test --permit-no-files
  • --jobs - 请改用 DENO_JOBS 环境变量
  • test --trace-ops - 请使用 test --trace-leaks
  • --ts - 请改用 --ext=ts

此外,您可以使用 DENO_LOG 环境变量而不是 RUST_LOG 来启用调试日志记录。

最后,配置文件中的 files 选项现在已弃用。

在 Deno v1.x 中,支持以下语法

{
  "test": {
    "files": {
      "include": ["**/*.ts"],
      "exclude": ["ignore.ts"]
    }
  }
}

在 Deno 2 中,files 配置已简化,并展平到父配置中

{
  "test": {
    "include": ["**/*.ts"],
    "exclude": ["ignore.ts"]
  }
}

导入断言已死,导入属性万岁

导入断言支持已在 Deno v1.46 中弃用,并且在 Deno 2 中不再可用。

原因是该提案经历了重大更改,包括将关键字从 assert 更新为 with,并重命名为 导入属性,此外,一些浏览器(例如 Chrome)也已经取消了对导入断言的支持。

以下是更新后的样子

- import data from "./data.json" assert { type: "json" };
+ import data from "./data.json" with { type: "json" };

Node.js 和 npm 兼容性

改进的 CommonJS 支持

自 1.0 版本发布以来,Deno 一直将 ES 模块作为主要模块系统,仅通过手动创建 require 提供对 CommonJS 的有限支持

import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
require("...");

虽然我们坚信 ES 模块是 JavaScript 的未来,但 2024 年的现状仍然包含许多依赖 CommonJS 的库和项目。

尽管 Deno 在过去一年中对 CJS 库的处理非常强大,但用户在集成 CommonJS 时,尤其是在他们自己的代码库中,偶尔会面临挑战。

在 Deno 2 中,对 CommonJS 模块的工作进行了多项改进,并使向 ES 模块的过渡更加容易

  • deno run index.cjs - Deno 现在可以执行 CommonJS 文件,前提是它们使用 .cjs 扩展名。Deno *不* 查找 package.json 文件和 type 选项来确定文件是 CommonJS 还是 ESM。

    使用此选项时,Deno 也不会自动安装依赖项,因此您需要预先手动运行 deno install 以确保所有必需的依赖项都可用。

// index.cjs
const express = require("express");

注意Deno 权限系统仍然有效,因此 require() 调用将提示 --allow-read 权限。

deno run index.cjs
┏ ⚠️  Deno requests read access to "/dev/example".
┠─ Learn more at: https://docs.deno.org.cn/go/--allow-read
┠─ Run again with --allow-read to bypass this prompt.
┗ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions) >
  • import cjs from "./index.cjs" - Deno 现在可以导入 CommonJS 文件,前提是它们使用 .cjs 扩展名。Deno *不* 查找 package.json 文件和 type 选项来确定文件是 CommonJS 还是 ESM。
// greet.cjs
module.exports = {
  hello: "world",
};
import greet from "./greet.cjs";
console.log(greet);
deno run main.js
{
  "hello": "world"
}
  • require(ESM) - Deno 现在支持 require ES 模块。只有当所需的模块不使用顶层 await 时,这才有可能。此更改应提高在使用依赖 CommonJS 和 ESM 的混合依赖项时的互操作性。
// greet.js
export function greet(name) {
  return `Hello ${name}`;
}
// esm.js
import { greet } from "./foo.js";

export { greet };
// main.cjs
const esm = require("./esm");
console.log(esm);
console.log(esm.greet("Deno"));
deno run --allow-read main.cjs
[Module: null prototype] { greet: [Function: greet] }
Hello Deno
  • 更好地建议处理 CommonJS 模块时出现的错误,引导您编写可工作的程序
// main.js
module.exports = {
  foo: "foo",
};
deno run main.js
error: Uncaught (in promise) ReferenceError: module is not defined
module.exports = {
^
    at file:///Users/ib/dev/deno/main.js:1:1

    info: Deno does not support CommonJS modules without `.cjs` extension.
    hint: Rewrite this module to ESM or change the file extension to `.cjs`.

自带 node_modules 是默认设置

“自带 node modules”功能在 Deno v1.38 中引入

ℹ️ 虽然我们仍然强烈建议不要依赖本地 node_modules 目录,但许多现有项目和框架都基于此目录将存在的假设运行。

但有时您仍然希望拥有本地 node_modules 目录,即使您没有 package.json - 例如,当使用 Next.js、Remix 或 Svelte 等框架时;或者当依赖于使用 Node-API 的 npm 包时,如 duckdbsqlite3esbuild 等。为了提高兼容性,如果一个项目包含 package.json 文件,Deno 将期望手动设置 node_modules 目录。


在之前的 Deno 版本中,您可以使用 --node-modules-dir 标志或配置文件中的 nodeModulesDir 选项来告诉 Deno 是否应创建 node_modules 目录。

Deno 2 更改了此配置选项 - 它不再是布尔值,而是一个包含三个选项的枚举

默认模式

deno run main.ts

# or

deno run --node-modules-dir=none main.ts

或使用配置文件

{
  "nodeModulesDir": "none"
}

这是 Deno 优先项目的默认模式 - 即没有 package.json 文件的项目。它自动将依赖项安装到全局缓存中,并且不创建本地 node_modules 目录。

ℹ️ 推荐 用于新项目。请注意,期望 node_modules 目录的框架将无法工作,此外,任何依赖于 postinstall 脚本的 npm 依赖项也将无法工作。

auto 模式

deno run --node-modules-dir=auto main.ts

或使用配置文件

{
  "nodeModulesDir": "auto"
}

auto 模式自动将依赖项安装到全局缓存中,并在项目根目录中创建本地 node_modules 目录。

ℹ️ 推荐 用于具有依赖于 node_modules 目录的 npm 依赖项的项目 - 大部分是使用捆绑器的项目,或具有带有 postinstall 脚本的 npm 依赖项的项目。

manual 模式

deno run --node-modules-dir=manual main.ts

或使用配置文件

{
  "nodeModulesDir": "manual"
}

manual 模式是使用 package.json 的项目的默认模式。此模式是 Node.js 使用的工作流程,需要使用 deno install/npm install/pnpm install 或任何其他包管理器进行显式安装步骤。

ℹ️ 推荐 用于使用 Next.js、Remix、Svelte、Qwik 等框架的项目;或 Vite、Parcel、Rollup 等工具。


建议使用默认的 none 模式,如果您遇到有关 node_modules 目录中缺少包的错误,请回退到 automanual 模式。

Node.js API 兼容性

在受支持的内置 Node.js API 方面再次取得了巨大进展,从而支持了更多流行的软件包

使用 deno test --doc 进行文档测试

JSDoc 是一种用于为 JavaScript 和 TypeScript 编写内联文档的格式。 deno docJSR 自动为其模块生成文档的方式就是使用 JSDoc。

JSDoc 允许我们直接在注释中编写代码示例

/**
 * ```ts
 * import { assertEquals } from "jsr:@std/assert/equals";
 *
 * assertEquals(add(1, 2), 3);
 * ```
 */
export function add(a: number, b: number) {
  return a + b;
}

但有一个问题…… 如何确保这些示例保持最新,并且不会代码腐烂呢?

Deno v1.10 添加了类型检查示例的功能,这在一定程度上有所帮助,但并未完全解决问题。 确保示例保持最新的唯一方法是实际执行它们。

在 Deno 2 中,deno test --doc 不仅对 JSDoc 中的示例进行类型检查,还会执行它们

在 Deno 2 中测试 JSDoc 示例的演示

要测试您的 JSDoc 示例,只需运行 deno test --doc,Deno 将自动发现并运行相关的代码块。

ℹ️ 如果您只想对示例进行类型检查,您仍然可以通过运行 deno check --doc 来实现。

但这还不是全部! 除了测试 JSDoc 示例之外,您还可以在 Markdown 文件中执行代码块

在 Deno 2 中测试 Markdown 代码块的演示

这是此功能的第一个迭代版本,我们欢迎任何反馈

TypeScript 更改

Deno v2.0 附带了 TypeScript 5.6,您可以在 Announcing TypeScript 5.6 博客文章中阅读更多相关信息。

为了帮助捕获常见的陷阱,现在默认启用以下 TypeScript 设置

此外,Deno 2 附带了对版本 22 的 @types/node 的内置支持,以便更轻松地对依赖 Node.js API 的代码进行类型检查。

最后,为了确保您的 compilerOptions 设置是最新的,我们已将其设为允许列表,因此如果您使用不受支持的选项,Deno 将会报错并标记出来。

致谢

没有我们社区的帮助,我们就无法构建 Deno! 无论是通过在我们的社区 Discord 服务器中回答问题还是报告错误,我们都非常感谢您的支持。 特别是,我们要感谢以下人员为 Deno 2 候选版本的发布做出的贡献:Andreas Deininger、Armaan Salam、Bedis Nbiba、Birk Skyum、Bob Callaway、Caleb Cox、Caleb Lloyd、Coty、Hajime-san、HasanAlrimawi、Ian Bull、Ivancing、Jake Abed、Kamil Ogórek、Kenta Moriuchi、Kyle Kelley、Mohammad Sulaiman、MrEconomical、MujahedSafaa、Pig Fang、Rano | Ranadeep、Roy Ivy III、Sean McArthur、Sʜɪᴍᴜʀᴀ Yū、Victor Turansky、Yazan AbdAl-Rahman、Zebreus、chirsz、cions、i-api、melbourne2991、seb、vwh 和 Łukasz Czerniawski。

您想加入 Deno 贡献者的行列吗? 请查看我们的贡献文档,我们下次会在列表中见到您。

感谢您关注我们的 Deno 2 候选版本,我们希望您喜欢使用 Deno 构建!

下一步是什么?

此候选版本正朝着我们的 2.0 版本迈进,预计会出现错误和问题。 如果您遇到任何问题,请在 GitHub issues(带有 2.0 标签)或在 我们 Discord 的专用 #deno-2-help 频道中告知我们。 我们正在积极监控这两个区域,以确保在我们的 2.0 版本发布之前修复所有主要错误。