Deno 1.31:package.json 支持
Deno 1.31 已发布,包含以下新特性和更改
package.json
支持- Node-API 稳定版
- 兼容层现已集成到运行时中
- 远程模块支持 npm 标识符
- FFI API 的重大更改
Deno
API 变更- 命令行界面更改
- 标准库变更
- V8 11.0
如果您已安装 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"
)。此外,这还可以在 scripts
部分中使用 deno task
运行项目特定的脚本。
注意:目前对“scripts”的支持仅限于简单的脚本。像
rimraf
或cross-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 标准库中用户态代码实现的 polyfills。随着 Deno 的每次发布,对 https://deno.land/std
的依赖都必须更新,这导致每次升级后都必须下载兼容层。此外,该层文件庞大(约 1.5Mb),在重复执行此代码时会导致启动速度进一步减慢。
为了解决这些问题,Deno 团队采取了根本性措施,改善了依赖 npm 包的用户体验——无论是通过 npm: 标识符还是新添加的 package.json 自动发现功能。现在,整个兼容层已嵌入到 Deno 运行时本身,并使用 V8 快照大幅减少了启动时间。这种更紧密的集成使得缺失 API 的 polyfill 更容易实现,并提升了已支持的内置 Node.js 模块的性能。
现在,要使用嵌入式 Node polyfills,您可以从 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 的重大更改
自 Deno 1.24 起,Deno 中的指针一直由指针数字(number 或 BigInt)表示,并为此提供了自定义的 Deno.PointerValue
类型。该类型也曾用于表示 64 位整数。
从 Deno 1.31 开始,指针现在表示为普通对象,空指针则为 null。这些对象直接由 V8 创建并由 V8 Fast API 支持,这意味着 FFI 在处理 "pointer"
类型参数和返回值时的性能相比以前的版本得到了进一步提升。指针对象是不透明的,不能直接从 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.Command
和 Deno.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
选项,允许向 API 传递一个 AbortSignal
以取消正在进行的操作。
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 compile
、deno_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
是标准模块中的文件服务器实现。得益于 文件系统 API 在两个运行时中的兼容性,它既可以在 Deno 中工作,也可以在 Deno Deploy 中工作。
然而,由于 Deno Deploy 中文件的 mtime
属性不可用,文件服务器无法对相同资源的请求返回 304
响应,并且当多次提供相同的大资源时,站点可能会变慢。
在此版本中,文件服务器已增加了对 Deno Deploy 环境中 ETag
头的支持。现在,它能够正确地对相同资源的请求返回 304 响应,并且由该文件服务器提供的站点得到了极大优化。
V8 11.0
本次发布升级到最新版 V8 (11.0,此前为 10.9)。