跳到主要内容
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 快照用于大幅缩短启动时间。这种更紧密的集成使得更容易 polyfill 缺少的 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 中的指针一直由指针数字(number 或 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。因此,从以前的版本迁移意味着

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

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

Deno API 的变更

API 稳定化

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

我们建议用户从 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 以取消正在进行的operation。

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/std@0.177.0/node/fs.ts) 或使用内置的 Node 模块规范符 (import fs from "node:fs")。

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

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

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

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

V8 11.0

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