跳到主要内容
Deno 2 终于来了 🎉️
了解更多
Deno 1.31 Deno 1.31 adds support for package.json, stabilizes Deno.Command API, Node-API and more...

Deno 1.31: 支持 package.json

Deno 1.31 已发布并标记,包含以下新功能和更改


如果您已经安装了 Deno,则可以通过运行以下命令升级到 1.31

deno upgrade

如果您是第一次安装 Deno

# MacOS and Linux
curl -fsSL https://deno.land/x/install/install.sh | sh

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

点击此处 获取更多安装选项。

package.json 支持

此版本带来了一项激动人心的新功能 - package.json 支持。Deno 现在更加易于访问,使开发人员能够轻松地从现有的 Node 项目过渡。

Deno 现在将自动检测 package.json 并使用它来安装和解析所使用的依赖项(例如 import express from "express")。此外,这还使能够使用 deno task 运行在 scripts 部分中定义的项目特定脚本。

注意:目前对“scripts”的支持仅限于简单的脚本。像 rimrafcross-env 这样的程序将无法使用;我们将在下一个版本中添加对这些程序的支持。

例如,假设我们有以下 package.json

{
  "name": "@deno/my-example-app",
  "description": "An example app created with Deno",
  "type": "module",
  "scripts": {
    "say-hello": "cowsay 'Hello from deno!'"
  },
  "dependencies": {
    "chalk": "^5.2"
  },
  "devDependencies": {
    "cowsay": "^1.5"
  }
}

使用以下脚本引用 chalk 通过裸说明符

// main.ts
import chalk from "chalk";
console.log(chalk.green("Hello from Deno!"));

我们可以运行此脚本

> deno run --allow-env --allow-sys main.ts
Hello from Deno!

或通过 deno task 执行 package.json 脚本

> deno task say-hello
Task say-hello cowsay 'Hello from deno!'
 __________________
< Hello from deno! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

对于更复杂的示例,您可以尝试运行一个示例 Vite 项目

$ deno run -A npm:create-vite vite-project --template vue
$ cd vite-project
$ deno task dev

重要的是要注意,Deno 仍然支持 web 标准导入映射,这仍然是 Deno 中映射裸说明符的首选方式。

与往常一样,Deno 致力于使开发尽可能流畅高效。我们对这项功能带来的可能性感到兴奋,并期待社区的反馈。

Node-API 稳定化

Deno 1.31 稳定了 Node-API(又称 N-API),这意味着使用依赖于 Node-API 的 npm 包时不再需要 --unstable 标志。

此外,Node-API 应用了许多错误修复,现在许多其他包可以使用而不会出现问题。我们计划在未来几周内解决剩下的错误。

兼容性层现在是运行时的一部分

Deno 1.31 通过将 Node.js 的兼容性层直接移入 Deno 运行时本身,为运行时带来了显著的改进。在之前的版本中,Node.js 的兼容性是通过 https://deno.land/std/node 提供的 - 这是一个在 Deno 标准库中使用用户代码实现的 polyfill 集合。随着每个 Deno 版本的发布,对 https://deno.land/std 的依赖都必须升级,这导致每次升级后都必须下载兼容性层。此外,该层非常大(约 1.5Mb),导致在重复执行此代码时启动速度进一步下降。

为了解决这些问题,Deno 团队采取了激进的措施来改善依赖于 npm 包的用户的情况 - 无论是通过 npm:说明符还是新添加的 package.json 自动发现。整个兼容性层现在嵌入在 Deno 运行时本身中,并且 V8 快照用于大幅减少启动时间。这种更紧密的集成使得更容易填充缺少的 API,并提高了已经支持的内置 Node.js 模块的性能。

要使用嵌入式 Node polyfill,您现在可以从 node: 说明符导入。例如,要导入 Node 的 fs 模块,请从 node:fs 导入。此更改将显著提高 Deno 应用程序的性能,并使 Deno 团队能够更轻松地支持和增强运行时与 Node.js 的兼容性。

npm 说明符在远程模块中受支持

以前,导入依赖于 npm 包的远程模块需要 --unstable 标志。现在不再需要。

自己试试看

deno run --allow-env --allow-sys https://gist.githubusercontent.com/dsherret/2273fbf9eb3c3ac73b4862cf6633c4cf/raw/442c6cea52f5a292359963a22fdab7fd7e4133ff/main.ts

FFI API 中的重大更改

自 1.24 以来,Deno 中的指针一直由指针号(数字或 BigInt)表示,并为此提供了一个自定义的 Deno.PointerValue 类型。该类型也用作 64 位整数的类型。

从 Deno 1.31 开始,指针现在表示为纯对象,或者对于空指针则为 null。这些对象由 V8 直接创建并由 V8 Fast API 支持,这意味着在使用 "pointer" 类型参数和返回值时,FFI 的性能已从之前的版本进一步提高。指针对象是不透明的,无法从 JavaScript 中直接操作。这意味着 FFI 的使用变得更加安全,因为指针欺骗不再像编写 JavaScript 数字那么容易。

这对尚不稳定的 FFI API 来说是一个重大更改。Deno.PointerValue 类型仍然存在,但现在代表 null | PointerObject,而 64 位整数参数和返回值现在明确使用类型 number | bigint。因此,从之前的版本迁移意味着

  • 在使用 Deno.PointerValue 来标记 64 位整数而不是指针的地方,用 number | bigint 替换它的使用。
  • null 替换作为空指针的 0。
  • Deno.UnsafePointer.offset(pointer, offset) 使用替换指针运算。

在必须将指针号转换为指针的地方(例如从 TypedArray 获取指针),使用 Deno.UnsafePointer.create(address)

Deno API 的更改

API 稳定化

此版本稳定了两个 API:Deno.CommandDeno.osUptime()。这意味着使用这些 API 时不再需要 --unstable 标志。

我们建议用户从 Deno.run() API 迁移到新的 Deno.Command API,因为我们计划将来弃用 Deno.run()

对稳定 API 的扩展

Deno.build.os 现在返回更多操作系统变体:"darwin" | "linux" | "windows" | "freebsd" | "netbsd" | "aix" | "solaris" | "illumos"。虽然其中一些未正式支持,但一些用户自己编译 Deno 并要求扩展操作系统列表。

Deno.resolveDns() 获得一个新的 signal 选项,允许将 AbortSignal 传递给 API 以取消正在进行的操作。

const ac = new AbortController();
const promise = Deno.resolveDns("www.example.com", "A", {
  nameServer: { ipAddr: "127.0.0.1", port: 4553 },
  signal: ac.signal,
});
ac.abort();

命令行界面变更

deno bundle 已弃用

deno bundle 命令不再受支持,不会出现在帮助输出中。虽然 Deno 目前没有立即删除它的计划,但鼓励用户切换到其他打包解决方案,例如 deno compiledeno_emit、esbuild、rollup 或其他。

需要注意的是,为浏览器打包 JavaScript 是一个复杂的过程,有多种选项和观点。deno bundle 不是浏览器打包的合适解决方案。它的主要功能是为在 Deno 中运行服务器端代码创建自包含文件,这导致用户之间存在混淆。

由于 Deno 继续支持 npm 和内置的 Node 模块,因此支持 deno bundle 变得更加困难。因此,鉴于用户空间中已经存在优秀的打包器,已决定从运行时本身删除此功能。

deno bench 的 JSON 报告器

deno bench 现在接受一个 --json 标志,它将以 JSON 格式打印基准测试结果。这允许以编程方式使用结果。

请注意,格式仍然不稳定,将来可能会改变。

$ deno bench --json bench_me.js
{
  "runtime": "Deno/1.31.0 x86_64-apple-darwin",
  "cpu": "Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz",
  "benches": [
    "origin": "file:///dev/bench_me.js",
    "group": null,
    "name": "Deno.UnsafePointerView#getUint32",
    "baseline": false,
    "result": {
      "ok": {
        "n": 49,
        "min": 1251.9348,
        "max": 1441.2696,
        "avg": 1308.7523755102038,
        "p75": 1324.1055,
        "p99": 1441.2696,
        "p995": 1441.2696,
        "p999": 1441.2696
      }
    }
  ]
}

感谢 Serhiy Barhamon 实现了此功能。

权限提示改进

从本版本开始,交互式权限提示现在接受一个新的选项 A。此选项允许为使用已授予域的所有后续 API 调用授予权限。

示例

$ deno repl
Deno 1.31.0
exit using ctrl+d, ctrl+c, or close()
> Deno.env.get("DENO")
┌ ⚠️  Deno requests env access to "DENO".
├ Run again with --allow-env to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) > A
✅ Granted all env access.
undefined
> Deno.env.get("FOOBAR")
undefined
>

以前这不可能,用户必须为每个请求不同于以前请求的值的 API 调用授予权限。这导致必须回答多个提示,而此更改使其更符合人体工程学,可以为某些域授予权限。

感谢 Asher Gomez 实现了此功能。

deno compile 支持静态可分析的动态导入

deno compile 现在理解可以在编译时解析的动态导入,即采用纯字符串文字的动态导入。

// main.ts
const { add } = await import("./add.ts");

console.log(add(1, 2));

// add.ts
export function add(a: number, b: number) {
  return a + b;
}
> deno compile main.ts
Compile file:///V:/example/main.ts
Emit example.exe
> ./example
3

deno fmt 的简短参数

deno fmt 通过 CLI 标志接受少量选项 - 所有选项都采用 --options-<option_name> 的形式。此版本添加了这些标志的简写版本,省略了标志名称的“options”部分。

示例

# before
deno fmt --options-line-width=100 --options-use-tabs=true

# after
deno fmt --line-width=100 --use-tabs=true

旧标志仍然受支持,但它们不包含在帮助输出中。

感谢 aryan02420 实现了此功能。

标准库变更

此标准库版本的主要更改是删除了 https://deno.land/std/node 模块。此代码已移至 Deno 主存储库,现在直接嵌入到 Deno 运行时中。对于依赖于 https://deno.land/std/node 的用户,我们建议将 std 版本固定到 0.177.0 版本 (https://deno.land/[email protected]/node/fs.ts),或者使用内置的 Node 模块说明符 (import fs from "node:fs")。

std/http/file_server.ts 在 Deno Deploy 中变得更高效

std/http/file_server.ts 是标准模块中的文件服务器实现。它可以在 Deno 和 Deno Deploy 中使用,这得益于 这两个运行时中 FS API 的兼容性

但是,由于 Deno Deploy 中的 文件无法使用 mtime 属性,文件服务器无法返回 304 响应来响应对同一资源的请求,并且在多次提供相同的大型资源时,站点速度可能会很慢。

在本版本中,文件服务器已添加对 Deno Deploy 环境中 ETag 标头的支持。它现在可以正确地返回 304 响应来响应对同一资源的请求,并且由文件服务器提供的站点已得到大幅优化。

V8 11.0

本版本升级到最新版本的 V8 (11.0,之前为 10.9)。