原文:Deno官方博客
作者:Bartek Iwańczuk、Andy Jiang 2024年9月19日
我们已经计划 Deno 的新主要版本多年了。多次看似即将发布,但我们意识到需要更多的工作来实现我们想要的功能。而现在,这一刻终于到来了。上个月,我们发布了最后一个 1.x 版本 1.46,今天我们发布了 Deno 2.0 的候选版本,包含了我们预计在最终版本中的所有内容。这是自 1.0 以来最大的一次更新,其中包括引入了 Node 的 process 全局对象等重大变更。我们还做出了一些哲学上的转变,比如更倾向于使用 deno install 代替现在已废弃的 deno cache。请继续阅读完整的更改列表,并分享你的反馈!
要试用该候选版本,请在终端中运行以下命令:
deno upgrade
deno upgrade rc
ℹ️ 如果你使用的是 Homebrew 等替代的分发方式,可能无法使用
deno upgrade。请按照 deno.com 上的安装说明进行操作,然后运行上述命令。
Deno 2.0 候选版本中的新功能
- 全局变量
window和process的变更 - 依赖管理
- 权限系统的变更
- API 变更
- 命令行界面的变更
- 导入断言被弃用,导入属性取而代之
- Node.js 和 npm 兼容性
- 通过
deno test --doc进行文档测试 - TypeScript 变更
全局变量的变更
Deno 2 带来了两个全局变量的重要变更——window 被移除,并引入了 Node 的 process。
我们在 Deno v1.0 中引入了 window 全局对象,目的是让 Deno 尽可能与浏览器兼容。不幸的是,window 全局变量成了用户问题的源头。
许多库通过检测 window 全局变量来判断是否在浏览器中运行,而不是检查 DOM 的存在。这导致了在 Deno 中的许多库出现了一类问题,因为 window 是全局可用的。
Deno 在 v1.40 中开始不鼓励使用 window 全局变量,建议改用 globalThis 或 self。
// 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/testing@1.0.2
# 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:preact@10.24.0
ℹ️ 现在在添加依赖时必须使用
jsr:或npm:前缀,以避免两个注册表中同名包的潜在歧义。如果你省略了前缀,Deno 将打印出正确的调用建议,检查哪个注册表包含该包。
此外,如果你的项目中包含 package.json 文件,Deno 将优先把 npm: 依赖添加到 package.json 中,而不是 deno.json。
cat package.json
{
"dependencies": {}
}
deno add npm:express
Add npm:express@5.0.0
cat package.json
{
"dependencies": { "express": "^5.0.0" }
}
你还可以使用 --dev 标志将“开发依赖”添加到 package.json 中:
deno add --dev npm:express
Add npm:express@5.0.0
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/testing@1.0.2
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(如 Worker 和 SharedArrayBuffer)实现。
--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.com/runtime/fundamentals/security/
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
# 授予读取 `file1.txt` 和 `file2.txt` 的权限
这使得无法为文件名中包含逗号的文件授予权限。
在 Deno 2 中,可以通过用另一个逗号转义逗号来实现:
deno run --allow-read=file,,.txt,file2.txt
# 授予读取 `file,.txt` 和 `file2.txt` 的权限
API 变更
稳定 API
Deno 2 稳定了以下几个 API:
WebGPUAPI 不再需要--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() 是一个不稳定的 API。
hint: 请使用 `--unstable-kv` 标志运行以启用该 API。
Deno API 的重大变更
ℹ️ 更多关于如何从已弃用 API 迁移的信息,请访问 Deno 1 到 2 的迁移指南
以下 API 已被移除:
Deno.BufferDeno.close()Deno.copy()Deno.customInspectDeno.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.certChainDeno.ConnectTlsOptions.certFileDeno.ConnectTlsOptions.privateKeyDeno.ListenTlsOptions.certChainDeno.ListenTlsOptions.certFileDeno.ListenTlsOptions.keyFile
以下接口已被移除:
Deno.CloserDeno.Reader和Deno.ReaderSyncDeno.Seeker和Deno.SeekerSyncDeno.Writer和Deno.WriterSync
此外,某些与 DNS 记录处理相关的接口名称已更改:
Deno.CAARecord改为Deno.CaaRecordDeno.MXRecord改为Deno.MxRecordDeno.NAPTRRecord改为Deno.NaptrRecordDeno.SOARecord改为Deno.SoaRecordDeno.SRVRecord改为Deno.SrvRecord
以下 API 中不再提供 "资源 ID":
Deno.FsWatcher.prototype.ridDeno.Conn.prototype.ridDeno.TlsConn.prototype.ridDeno.TcpConn.prototype.ridDeno.UnixConn.prototype.ridDeno.FsFile.prototype.ridDeno.Listener.prototype.ridDeno.TlsListener.prototype.rid
最后,部分 API 被“软弃用”,这些 API 仍然可以使用,但不再接收更新或 bug 修复。建议尽快迁移到对应的稳定 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()代替
命令行界面(CLI)变更
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 支持
自 Deno 1.0 版本以来,Deno 一直优先使用 ES 模块作为主要的模块系统,只为 CommonJS 提供了有限的支持,通常通过手动创建 require:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
require("...");
尽管我们坚信 ES 模块是 JavaScript 的未来,但在 2024 年,许多库和项目仍然依赖于 CommonJS。
过去一年中,Deno 已经可以很好地处理 CJS 库,但用户在集成 CommonJS 尤其是自己的代码时,仍可能遇到一些问题。
在 Deno 2 中,针对 CommonJS 模块进行了以下改进,帮助用户更好地使用它们,并更容易过渡到 ES 模块:
- 支持直接运行 CommonJS 文件: 现在 Deno 可以执行带
.cjs扩展名的 CommonJS 文件,如:
deno run index.cjs
使用此选项时,Deno 不会自动安装依赖项,因此你需要手动运行 deno install 以确保所有依赖项可用。
// index.cjs
const express = require("express");
注意: Deno的权限系统仍然有效,因此调用将会提示需要权限。
deno run index.cjs
┏ ⚠️ Deno requests read access to "/dev/example".
┠─ Learn more at: https://docs.deno.com/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 现在能够导入使用.cjs扩展名的 CommonJS 文件。Deno 不会查找package.json文件和类型选项来确定文件是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 现在支持加载 ES 模块了。但这仅在被加载的模块不使用顶级等待(Top-Level Await)的情况下才可行。这一改变旨在提升互操作性,以便在同时使用依赖于 CommonJS 和 ES 模块的混合依赖项时,能够更流畅地工作。
// 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”机制
Deno 2 进一步完善了 “自带 node_modules” 功能,这一功能 首次引入于 Deno v1.38。
ℹ️ 虽然我们仍然强烈建议不要依赖于本地的
node_modules目录,但许多现有项目和框架都是基于这样一个假设来运行的,即这个目录将会存在。
但有时,即便没有package.json文件,你可能仍希望拥有一个本地的node_modules目录——例如,在使用Next.js、Remix或Svelte等框架时;或是当你依赖使用Node API的npm包时,如duckdb、sqlite3、esbuild等。为了提高兼容性,如果项目包含package.json文件,Deno将会期望node_modules目录已被手动设置。
在之前的 Deno 版本中,你可以使用 --node-modules-dir 标志或配置文件中的 nodeModulesDir 选项来告诉 Deno 是否应该创建 node_modules 目录。
Deno 2 改变了这个配置选项 - 它不再是一个布尔值,而是一个有三种选项的枚举:
默认模式
deno run main.ts
# 或者
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 目录中缺少包的错误时,退回到 auto 或 manual 模式。
Node.js API 兼容性
Deno 2 对 Node.js 内置 API 的支持再次取得了显著进展,从而支持了更多流行的包:
node:crypto接口得到了多项更新:- 支持 MD4 摘要函数,解决了
npm:docusaurus的兼容问题。 - 修复了
Cipheriv.update(string, undefined)的问题。 - 修复了
Decipheriv在关闭autoPadding选项时的表现。 - 支持导出 JWK 公钥和导入 EC、RSA、八位组密钥对(octet key pairs)等。
- 支持
npm:web-push。
- 支持 MD4 摘要函数,解决了
async_hooks.AsyncLocalStorage更加高效和稳定。- **支持
npm:detect-port和 **npm:portfinder库。 - **改进对
npm:ssh2和 **npm:elastic-apm-node的支持。 node:wasi现已内置。node:events** 和 **node:util的覆盖范围得到了扩展。npm:puppeteer更加稳定,修复了FileHandle#writeFileAPI 和 socket 升级处理。- 改进对
node:constants、node:fs、node:path、node:vm** 和 **node:zlib等模块的支持,导出缺失的常量。 node:trace_events已内置,避免崩溃。node:timers现在导出promises符号。npm:qwik、npm:hono** 和 **npm:playwright库的稳定性得到了提高。
使用 deno test --doc 测试文档中的代码
JSDoc是一种用于编写 JavaScript 和 TypeScript 内联文档的格式。它是 deno doc JSR 自动为其模块生成文档的方式。
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 中的示例进行类型检查,还执行它们:
要测试您的 JSDoc 示例,只需运行deno test --doc,Deno 就会自动发现并运行相关的代码块。
ℹ️如果你只想对示例进行类型检查,你仍然可以通过运行来进行
deno check --doc。
但这还不是全部!除了测试 JSDoc 示例,你还可以在 Markdown 文件中执行代码块:
这是该功能的首次迭代,我们 非常欢迎任何反馈。
TypeScript 变化
Deno 2.0 搭载了 TypeScript 5.6,详细内容可以参考 TypeScript 5.6 发布公告 博客。
为了帮助开发者捕捉常见问题,以下 TypeScript 配置默认启用:
useUnknownInCatchVariablesnoImplicitOverride
此外,Deno 2 内置了对 @types/node 版本 22 的支持,简化了依赖 Node.js API 的代码的类型检查。
为了确保你的 compilerOptions 设置始终是最新的,Deno 现在对配置选项进行了白名单处理。如果你使用了不受支持的选项,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 版本发布之前修复所有主要的程序缺陷。