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

Deno 1.8 版本说明

今天我们发布了 Deno 1.8.0。此版本包含大量新功能和稳定性改进

如果您已经安装了 Deno,则可以通过运行 deno upgrade 来升级到 1.8。如果您是第一次安装 Deno,则可以使用以下方法之一

# Using Shell (macOS and Linux):
curl -fsSL https://deno.land/x/install/install.sh | sh

# Using PowerShell (Windows):
iwr https://deno.land/x/install/install.ps1 -useb | iex

# Using Homebrew (macOS):
brew install deno

# Using Scoop (Windows):
scoop install deno

# Using Chocolatey (Windows):
choco install deno

新功能和更改

实验性 WebGPU API 支持

WebGPU API 为开发人员提供了一种低级别、高性能、跨架构的方式,用于从 JavaScript 对 GPU 硬件进行编程。它是 Web 上 WebGL 的有效继任者。该规范尚未最终确定,但目前正在 Firefox、Chromium 和 Safari 中添加支持;现在也已在 Deno 中添加。

此 API 使您可以从 Deno 中访问 GPU 渲染和通用 GPU 计算。一旦完成、稳定并取消标记,这将提供一种可移植的方式来访问来自 Web、服务器和开发人员机器的 GPU 资源。

GPU 使程序员能够使某些数值算法高度并行。这不仅对渲染图形和游戏有用。GPU 在机器学习中的有效使用使更复杂的网络成为可能——即所谓的深度学习。计算机视觉、翻译、图像生成、强化学习等方面的快速发展都源于对 GPU 硬件的有效使用。

如今,大多数神经网络都在 Python 中定义,计算卸载到 GPU。我们相信,如果存在适当的基础设施,JavaScript 而不是 Python 可以作为表达数学思想的理想语言。在 Deno 中开箱即用地提供 WebGPU 支持是朝着这个方向迈出的一步。我们的目标是在 Deno 上运行 Tensorflow.js,并进行 GPU 加速。我们预计这将在未来几周或几个月内实现。

以下是一个基本示例,演示如何访问连接的 GPU 设备,以及读取名称和支持的功能

// Run with `deno run --unstable https://deno.org.cn/blog/v1.8/webgpu_discover.ts`

// Try to get an adapter from the user agent.
const adapter = await navigator.gpu.requestAdapter();
if (adapter) {
  // Print out some basic details about the adapter.
  console.log(`Found adapter: ${adapter.name}`);
  const features = [...adapter.features.values()];
  console.log(`Supported features: ${features.join(", ")}`);
} else {
  console.error("No adapter found");
}

以下是一个小例子,演示了 GPU 使用渲染着色器在绿色背景上渲染一个简单的红色三角形

$ deno run --unstable --allow-write=output.png https://raw.githubusercontent.com/crowlKats/webgpu-examples/f3b979f57fd471b11a28c5b0c91d0447221ba77b/hello-triangle/mod.ts

A simple red triangle on a green background

请注意使用 WebAssembly 来写入 PNG。有关更多示例,请访问以下存储库:https://github.com/crowlKats/webgpu-examples

最终的 PR 重量为 15.5k 行代码,并在打开后花了整整 5 个月的时间才合并。感谢 crowlKats 将 WebGPU 集成到 Deno 的领导。我们还要感谢所有对 wgpu 和 gfx-rs 项目做出贡献的人,这些项目是 Deno 中 WebGPU 实现的基础。特别感谢 WebGPU 规范编辑和 wgpu 及 gfx-rs 的主要开发人员 kvark,他们在实现 WebGPU API 期间提供的出色指导。

ICU 支持

ICU 支持一直是 Deno 存储库中第二受欢迎的功能。我们很高兴地宣布,Deno v1.8 附带了完整的 ICU 支持。

所有依赖 ICU 的 JavaScript API 现在都应该与浏览器 API 匹配。

在 REPL 中尝试一下

$ deno
Deno 1.8.0
exit using ctrl+d or close()
> const d = new Date(Date.UTC(2020, 5, 26, 7, 0, 0));
undefined
> d.toLocaleString("de-DE", {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
});
"Freitag, 26. Juni 2020"

改进的覆盖率工具:deno coverage

此版本扩展了我们的覆盖率基础设施,以添加一些很棒的新功能。此版本中的主要变化是覆盖率处理现在分为覆盖率收集和覆盖率报告。

以前,覆盖率收集和报告会在单个子命令中进行,方法是在启动 deno test 时指定 --coverage 标志。现在,deno test--coverage 标志接受一个参数——一个路径,用于指定存储收集的配置文件的目录。这是覆盖率收集。在第二步中,您现在使用存储覆盖率配置文件的目录的路径来调用 deno coverage。此子命令可以将报告作为漂亮的文本输出直接返回到控制台,或者它可以输出一个 lcov 文件(--lcov 标志),供 genhtml、coveralls.io 或 codecov.io 等工具使用。

我们已经在 deno_std 上对该功能进行了测试。我们为每次提交上传覆盖率报告到 codecov.io。您可以在此处查看它们 https://codecov.io/gh/denoland/deno_std。添加此功能很简单,只需在我们的 GitHub Actions 工作流中进行 10 行更改

- name: Run tests
-        run: deno test --unstable --allow-all
+        run: deno test --coverage=./cov --unstable --allow-all
+
+      - name: Generate lcov
+        run: deno coverage --unstable --lcov ./cov > cov.lcov
+
+      - name: Upload coverage
+        uses: codecov/codecov-action@v1
+        with:
+          name: ${{ matrix.os }}-${{ matrix.deno }}
+          files: cov.lcov

有关与 coveralls.io 集成的示例,请参见以下存储库:https://github.com/lucacasonato/deno_s3

导入映射现已稳定

导入映射 已在 Chrome 89 中稳定,之后我们的实现已更新以匹配规范的最新修订版,现在也被认为是稳定的。这意味着在使用 --import-map 时不再需要 --unstable 标志。

$ deno run --import-map=./import_map.json ./mod.ts

此外,--import-map 标志现在不仅接受本地路径,还接受 URL,允许您从远程服务器加载导入映射。

$ deno run --import-map=https://example.com/import_map.json ./mod.ts

导入映射允许用户为依赖项使用所谓的“裸”说明符,而不是相对或绝对文件/http URL

// Deno does not support such specifiers by default,
// but by providing an import map, users can remap bare specifiers
// to some other URLs.
import * as http from "std/http";
{
  "imports": {
    "std/http": "https://deno.land/[email protected]/http/mod.ts"
  }
}

用户应牢记,导入映射**不是**可组合的:这意味着您只能为 deno run/deno test 提供单个导入映射。因此,库作者仍应使用常规的非裸说明符(相对或绝对文件/http URL);否则,库的用户将需要手动将您的库(以及您的库依赖项)的裸说明符添加到他们的导入映射中。

导入映射的一个更有用的功能是能够将常规说明符重新映射到完全不同的说明符。例如,如果您有一些损坏的依赖项,它深嵌在您的模块图中,您可以在它被上游修复之前使用修复后的版本替换它,或者如果您使用构建过程在您的模块文件名中添加哈希,您可以在源代码中引用没有哈希的文件,并仅在运行时使用导入映射重新映射说明符。

有关更多示例和详细说明,请参阅 规范

支持使用身份验证令牌获取模块

并非所有代码都可以在公共互联网上公开获得。以前,Deno 没有能力从需要身份验证的服务器下载代码。在此版本中,我们添加了用户为每个域指定身份验证令牌的功能,这些身份验证令牌在首次获取模块时使用。

为此,Deno CLI 将查找名为 DENO_AUTH_TOKENS 的环境变量,以确定在请求远程模块时应使用哪些身份验证令牌。环境变量的值采用 n 个用分号 (;) 分隔的令牌的格式,其中每个令牌的格式为 {token}@{hostname[:port]}

例如,单个令牌将类似于以下内容

[email protected]

多个令牌将类似于以下内容

[email protected];[email protected]:8080

当 Deno 去获取一个远程模块时,如果该模块的域名与远程模块的域名匹配,Deno 将会将请求的 Authorization 头设置为 Bearer {token} 的值。这使得远程服务器可以识别该请求是一个与特定认证用户相关的授权请求,并提供对服务器上相应资源和模块的访问权限。

有关更详细的使用指南和配置环境以从私有 GitHub 仓库中提取的说明,请查看相关的用户手册条目

Deno.test 的退出清理器

Deno.test API 已经有了两个清理器,帮助确保您的代码没有“泄露”操作或资源 - 也就是说,在测试用例结束之前所有打开的文件/网络句柄都被关闭,并且没有更多挂起的系统调用。

Deno 1.8 添加了一个新的清理器,确保测试的代码不会调用 Deno.exit()。错误的退出语句可能会发出误报的测试结果,并且最常被误用或忘记被移除。

这个清理器默认情况下对所有测试都启用,但可以通过在测试定义中将 sanitizeExit 布尔值设置为 false 来禁用。

Deno.test({
  name: "false success",
  fn() {
    Deno.exit(0);
  },
  sanitizeExit: false,
});

// This test is never run
Deno.test({
  name: "failing test",
  fn() {
    throw new Error("this test fails");
  },
});

您可以自己运行此脚本:deno test https://deno.land/blog/v1.8/exit_sanitizer.ts

Deno.permissions API 现已稳定

Deno 的安全模型基于权限。目前这些权限只能在应用程序启动时授予。这在大多数情况下都能很好地工作,但在某些情况下,在运行时请求/撤销权限是更好的用户体验。

在 Deno 1.8 中,现在有一个稳定的 API 用于 queryrequestrevoke 权限。这些 API 包含在 Deno.permissions 对象中。以下是如何工作的示例

function homedir() {
  try {
    console.log(`Your home dir is: ${Deno.env.get("HOME")}`);
  } catch (err) {
    console.log(`Failed to get the home directory: ${err}`);
  }
}

// Try to get the home directory (this should fail, as no env permission yet).
homedir();

const { granted } = await Deno.permissions.request({ name: "env" });
if (granted) {
  console.log(`You have granted the "env" permission.`);
} else {
  console.log(`You have not granted the "env" permission.`);
}

// Try to get the home directory (this should succeed if the user granted
// permissions above).
homedir();

await Deno.permissions.revoke({ name: "env" });

// Try to get the home directory (this should fail, as the permission was
// revoked).
homedir();

您可以自己运行此脚本:deno run https://deno.land/blog/v1.8/permission_api.ts

此版本带来了与符号链接相关的四个 API 的稳定性

  • Deno.link
  • Deno.linkSync
  • Deno.symlink
  • Deno.symlinkSync

在稳定之前,这些 API 经过了安全审查,需要适当的权限才能使用它们。

Deno.linkDeno.linkSync 需要源路径和目标路径的读写权限。

Deno.symlinkDeno.symlinkSync 需要目标路径的写权限。

更细粒度的 Deno.metrics

随着 Deno 变得更加稳定,对开发者来说,拥有简单的方法来为他们的应用程序提供检测变得越来越重要。这从最低级别开始,从运行时本身开始。在 Deno 中,JS 中所有特权操作(那些转到 Rust 的操作)都是通过 JS 和 Rust 之间的单个中心接口完成的。我们称那些通过该接口的请求为“操作”。例如,调用 Deno.open 将会调用 op_open_async 操作到特权端,该操作将返回已打开文件的资源 ID(或错误)。

两年前,在 2018 年 10 月 11 日,我们添加了一种方法,让您可以查看 Rust 和 JS 之间所有操作的指标:Deno.metrics。该 API 目前公开了已启动和完成的同步和异步操作的数量,以及通过操作接口发送的数据量。到目前为止,这仅限于所有不同操作的组合数据。没有办法找出哪些操作被调用了多少次,只有所有操作的总体情况。

在使用 --unstable 运行时,此版本在 Deno.metrics 中添加了一个名为 ops 的新字段。此字段包含有关 API 被调用频率以及通过它传输了多少数据的每个操作信息。这使得运行时能够进行更加细粒度的检测。

以下是如何工作的示例

$ deno --unstable
Deno 1.8.0
exit using ctrl+d or close()
> Deno.metrics().ops["op_open_async"]
undefined
> await Deno.open("./README.md")
File {}
> Deno.metrics().ops["op_open_async"]
{
  opsDispatched: 1,
  opsDispatchedSync: 0,
  opsDispatchedAsync: 1,
  opsDispatchedAsyncUnref: 0,
  opsCompleted: 1,
  opsCompletedSync: 0,
  opsCompletedAsync: 1,
  opsCompletedAsyncUnref: 0,
  bytesSentControl: 54,
  bytesSentData: 0,
  bytesReceived: 22
}

在即将发布的版本中,这些新信息将被 Deno.test 中的异步操作清理器使用,以便在异步操作在测试完成之前没有完成时提供更实用的错误信息。我们已经看到这个功能被用来检测应用程序并将数据传送到监控软件中

screenshot of a website with a table displaying the output of Deno.metrics

deno fmt 的 JSON 支持

deno fmt 现在可以格式化 .json.jsonc 文件。就像 JS/TS 一样,格式化程序也会格式化 markdown 文件中的 json 和 jsonc 代码块。

Deno.emit 的 IIFE 捆绑支持

内置捆绑器现在可以以立即执行函数表达式 (IIFE) 格式发出捆绑包。

默认情况下,输出格式仍然是 esm,但用户可以通过将 EmitOptions.bundle 选项设置为 iife 来更改此设置

const { files } = await Deno.emit("/a.ts", {
  bundle: "iife",
  sources: {
    "/a.ts": `import { b } from "./b.ts";
        console.log(b);`,
    "/b.ts": `export const b = "b";`,
  },
});

console.log(files["deno:///bundle.js"]);

结果是

(function() {
    const b = "b";
    console.log(b);
    return {
    };
})();

您可以自己运行此脚本:deno run --unstable https://deno.land/blog/v1.8/emit_iife.ts

这对于为不支持 ESM 的旧版浏览器创建捆绑包特别有用。

deno lsp 现已稳定

在过去几个月里,我们一直在开发 Deno 扩展的替代方案,用于 VS Code,作为我们旧的编辑器集成的替代方案。旧扩展只适用于 VS Code,解析的类型并不总是与 Deno CLI 中的类型匹配。

在 Deno 1.6 中,我们发布了 deno lsp,一个 Deno 的内置语言服务器,处于 canary 状态。LSP 使我们能够仅从单个代码库为所有支持 LSP 的编辑器提供编辑器集成。内置语言服务器是基于与 Deno CLI 其他部分相同的架构构建的 - 因此它以与 CLI 其他部分相同的方式提供 TypeScript 诊断信息。

两周前,在 Deno 1.7.5 中,我们稳定了 deno lsp,并将我们的官方 VS Code 扩展切换到使用它。到目前为止,我们已经收到了一些很好的反馈,并将努力解决所有报告的问题。如果您在使用扩展时遇到了问题,请在我们的问题跟踪器中报告它。我们无法解决我们不知道的问题。

除了官方的 VS Code 集成之外,还创建了更多基于 deno lsp 的社区集成

TypeScript 4.2

Deno 1.8 带有最新稳定版本的 TypeScript。

有关 TypeScript 4.2 中新功能的更多信息,请参见宣布 TypeScript 4.2