Deno 1.23 已标记并发布,其中包含以下新功能和更改
- 默认情况下不进行类型检查
- 移除不稳定的
Deno.sleepSync
API - 文件监视器监视动态导入
deno task
更新deno fmt
更新- 新的不稳定
Deno.getGid()
API deno info
支持--config
和--no-config
标志- 在 REPL 中强制换行
- FFI API 更新
- Windows 上支持 SIGINT 和 SIGBREAK 信号监听
CompressionStream
和DecompressionStream
中支持"deflate-raw"
- TypeScript 4.7
flags
标准模块更改assertThrows
和assertRejects
更改
如果您已经安装了 Deno,可以通过运行以下命令升级到 1.23
deno upgrade
如果您是第一次安装 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
默认情况下不进行类型检查
Deno 始终会在要求执行程序时运行类型检查。但是,评估和类型检查是完全不同的操作,涉及完全不同的编译器,每个编译器都有完全不同的执行速度。评估代码使用 Google 的 V8,而类型检查使用 Microsoft 的 TypeScript 编译器。类型检查非常慢,通常需要几秒钟才能完成。另一方面,V8 启动和评估非常快。
如今,大多数程序员通过 LSP 在他们的编辑器中与类型检查器进行交互。这意味着他们在编程时会不断获得提示和完成。在 deno run
操作中默认插入另一个完整的类型检查步骤没有意义。类型检查更像是一个类似于 linting 的操作,您在 CI 期间执行此操作以确保没有类型错误。
还应强调的是,与类型检查不同,类型剥离是一个快速操作(在源代码大小方面是线性时间)。Deno 将默认进行类型剥离,而不是类型检查。
如果您仍然想要以前的行为(类型检查然后执行),请使用 --check
标志。
我们已经计划了几个月要进行此更改,确保向用户发出警告并引入 --check
标志。查看 v1.22 中的说明.
此更改影响 deno run
、deno eval
和 deno cache
。下表描述了各种子命令的类型检查行为。这里“本地”意味着只有来自本地代码的错误才会导致类型错误,从 https URL(远程)导入的模块可能存在未报告的类型错误。(要为所有模块启用类型检查,请使用 --check=all
。)
子命令 | 类型检查模式 |
---|---|
deno bench |
📁 本地 |
deno bundle |
📁 本地 |
deno cache |
❌ 无 |
deno check |
📁 本地 |
deno compile |
📁 本地 |
deno eval |
❌ 无 |
deno repl |
❌ 无 |
deno run |
❌ 无 |
deno test |
📁 本地 |
Deno.sleepSync
API
移除不稳定的 在此版本中,Deno.sleepSync
已被移除,因为由于此功能已经可以通过现有的 Web API 获得,因此对它没有明确的必要性。此外,它很可能会引起问题:Deno.sleepSync
完全阻塞了事件循环。例如,如果它在 Web 服务器处理程序函数中被调用,服务器将在返回之前停止为请求提供服务。
如果您真的想要此功能,可以通过使用以下函数来实现它
function sleepSync(timeout) {
const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);
Atomics.wait(int32, 0, 0, timeout);
}
文件监视器监视动态导入
从 v1.23 开始,内置文件监视器(您可以使用 --watch
标志激活它)还将监视动态导入的文件的更改。
// mod.ts <--- this file was being watched
import foo from "./foo.ts"; // <--- this file was also being watched
console.log(foo);
const bar = await import("./bar.ts"); // <--- this file was not being watched in previous versions;
// starting with v1.23 any changes to `bar.ts` will also cause the process to restart
此功能已允许在 Fresh Web 框架中获得 更好的开发体验。
deno task
更新
Deno 包含一个不稳定的 deno task
子命令,它提供了一种跨平台的方式来定义和执行特定于代码库的自定义命令。此版本包含一些改进。
--cwd <path>
标志
新的 deno task
具有一个属性,默认情况下,它使用 Deno 配置文件(例如 deno.json)的目录作为当前工作目录来执行命令。这允许任务使用相对路径,并且无论您从哪个子目录树中执行 deno task,它都可以继续工作。
虽然这种行为在大多数情况下都是想要的,但在某些情况下它却不是。在这些情况下,您现在可以提供一个 --cwd <path>
标志。
例如,给定一个名为 wasmbuild
的任务,它位于 deno.json 文件中
# use the sub directory project1 as the cwd for the task
deno task --cwd project1 wasmbuild
# use the cwd (project2) as the cwd for the task
cd project2 && deno task --cwd . wasmbuild
任务定义中的重定向
添加了一些重定向支持,以提供一种将 stdout 和/或 stderr 管道到文件的方法。
例如,以下内容将 deno run main.ts
的 stdout 重定向到文件系统上的名为 file.txt
的文件,前提是在 deno 任务中定义并运行 deno task collect
{
"tasks": {
"collect": "deno run main.ts > file.txt"
}
}
要改为重定向 stderr,请使用 2>
而不是 >
deno run main.ts 2> file.txt
要重定向 stdout 和 stderr,请使用 &>
deno run main.ts &> file.txt
要追加到文件,而不是覆盖现有文件,请使用两个右尖括号而不是一个
deno run main.ts >> file.txt
可以通过重定向到 /dev/null
来抑制命令的 stdout、stderr 或两者。这在跨平台情况下都有效,包括 Windows。
# suppress stdout
deno run main.ts > /dev/null
# suppress stderr
deno run main.ts 2> /dev/null
# suppress both stdout and stderr
deno run main.ts &> /dev/null
请注意,未实现多个重定向,并且目前不支持。
cat
和 xargs
跨平台 deno task
具有几个内置的跨平台命令,可以帮助减少冗长。此更新添加了 cat
和 xargs
的基本实现,适用于 Linux、Mac 和 Windows。
请注意,并非所有标志都已实现,请向 deno_task_shell 存储库报告任何问题。还要记住,您始终可以通过在 Linux 和 Mac 上(sh -c <command>
)通过 sh
来运行本机系统命令,以非跨平台的方式运行它。
deno fmt
更新
deno fmt
现在默认情况下会格式化 .cjs
、.cts
、.mjs
和 .mts
文件。
此外,类型中的一些不必要的括号将被自动移除。例如…
type Test = (string | number);
…现在将格式化为…
type Test = string | number;
Deno.getGid()
API
新的不稳定 在 v1.23 中,我们添加了一个新的不稳定 API:Deno.getGid()
。
使用此 API,您可以检索用户组的 ID。请注意,此 API 在 Linux 和 macOS 上有效,但在 Windows 上将返回 null
。
console.log(Deno.getGid());
// 20
此 API 需要 --allow-env
权限标志。
感谢 James Bradlee 为此功能做出贡献。
deno info
支持 --config
和 --no-config
标志
此版本添加了对 --config
和 --no-config
标志的支持。在之前的版本中,deno info
会自动查找 deno.json
文件,但没有办法手动指定配置文件或完全禁用它。
感谢 Mark Ladyshau 为此功能做出贡献。
在 REPL 中强制换行
此版本对 REPL 做了一些小的改善,提升了用户体验。
现在使用 ctrl + s
组合键可以在 REPL 中编辑代码时强制换行。
感谢 @sigmaSd 为此功能做出贡献。
FFI API 更新
以前,当通过 FFI 调用的函数返回 64 位数字时,会返回普通的 JavaScript 数字。但是,JavaScript 数字只有 53 位整数精度,这意味着有时会得到不正确的结果。通过此更改,将返回 BigInt
。此更改还允许将 BigInt
值作为参数传递。
感谢 Elias Sjögreen 为此功能做出贡献。
在 Windows 上监听 SIGINT 和 SIGBREAK 信号的支持
此版本添加了在 Windows 上监听 SIGINT (ctrl+c) 和 SIGBREAK (ctrl+break) 的功能。
Deno.addSignalListener("SIGINT", () => {
console.log("Received ctrl+c");
});
Deno.addSignalListener("SIGBREAK", () => {
console.log("Received ctrl+break");
});
在 手册 中了解有关操作系统信号的更多信息。
对于在 Windows 上支持 Deno.kill
SIGINT 和 SIGBREAK,请关注问题 #14866。
感谢 Geert-Jan Zwiers 和 @juzi5201314 为此功能做出贡献。
CompressionStream
和 DecompressionStream
中支持 "deflate-raw"
在 Deno 现在通过 RFC1951 中指定的 "deflate-raw"
格式字符串支持“DEFLATE 算法”。(不要与 "deflate"
混淆,"deflate"
是“ZLIB 压缩数据格式” RFC1950。)
let input = await Deno.open("README.md");
const compressed = input.readable.pipeThrough(
new CompressionStream("deflate-raw"),
);
let output = await Deno.open("README.md.zz", { create: true, write: true });
compressed.pipeTo(output.writable);
TypeScript 4.7
Deno v1.23 附带了最新稳定版本的 TypeScript。有关 TypeScript 中新功能的更多信息,请参阅 TypeScript 的 4.7 博客文章
flags
标准模块的更改
对 std/flags
最初是 minimist
的分支,直到最近才对其进行任何实质性更改。
在此版本中,对 parse
函数有两个重大更改。
collect
选项
collect
选项是一个新选项,用于指定选项参数是否可收集。当您在 collect
选项中指定参数名称时,相同参数的多次出现将被收集到数组中。
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
console.log(parse(Deno.args, { string: "foo", collect: "foo" }));
执行如下
$ deno run cli.js
{ _: [], foo: [] }
$ deno run cli.js --foo 1
{ _: [], foo: [ "1" ] }
$ deno run cli.js --foo 1 --foo 2
{ _: [], foo: [ "1", "2" ] }
$ deno run cli.js --foo 1 --foo 2 --foo 3
{ _: [], foo: [ "1", "2", "3" ] }
请注意,解析结果中的 foo
始终具有 string[]
类型。
在此更改之前,所有参数都是自动可收集的,并且具有 T | T[]
类型,其中 T
通常是 boolean
或 string
。
我们发现这种行为并不合理,因为在大多数情况下,大多数参数都不应该多次指定,但由于这种行为,工具作者总是需要使用 Array.isArray()
检查参数类型。
因此,这种行为变为可选,并且此收集功能仅在 collect
选项中明确指定时才会发生。
要迁移,如果您的 CLI 工具使用数组类型参数,请在 collect
选项中指定参数名称。
negatable
选项
negatable
选项是一个新选项。如果您在 negatable
中指定参数名称,那么 --no-arg
形式的标志将被视为 --arg=false
。
以下是一个示例
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
console.log(parse(Deno.args, { boolean: "foo", negatable: "foo" }));
执行如下
$ deno run cli.js
{ _: [], foo: false }
$ deno run cli.js --foo
{ _: [], foo: true }
$ deno run cli.js --no-foo
{ _: [], foo: false }
negatable
也可以与 string
一起使用
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
console.log(
parse(Deno.args, {
string: "foo",
negatable: "foo",
default: { foo: "bar" },
}),
);
执行方式如下
$ deno run cli.js
{ _: [], foo: "bar" }
$ deno run cli.js --foo baz
{ _: [], foo: "baz" }
$ deno run cli.js --no-foo
{ _: [], foo: false }
即使 foo
指定为 string
选项,foo
也会变为 false
。这对于删除选项的默认值很有用,如上述示例所示。
在之前的版本中,这种可否定行为默认应用于每个参数,但我们发现这并不合理。因此,它被更改为可选。
要迁移,如果您的 CLI 工具依赖于此 --no-arg
类型参数,请在 negatable
选项中指定参数名称。
感谢 Benjamin Fischer 为此功能做出贡献。
assertThrows
和 assertRejects
的更改
对 接受 errorCallback
作为第二个参数的 assertThrows
的签名已弃用。相反,assertThrows
现在将返回抛出的错误值。
如果您使用以下任何断言
import { assertThrows } from "https://deno.land/[email protected]/testing/asserts.ts";
assertThrows(
() => someFunc(),
(err) => {
// some assertions about err
},
);
请将其更新为以下形式
import { assertThrows } from "https://deno.land/[email protected]/testing/asserts.ts";
const err = assertThrows(
() => someFunc(),
);
// some assertions about err
此更改背后的动机是 errorCallback
仅接受对抛出值的同步断言。通过此更改,您可以对抛出的值执行任何断言,包括异步操作。
相同的更改也应用于 assertRejects
函数。它返回的 Promise 现在会解析为从内部 Promise 拒绝中检索到的错误。
感谢 Mark Ladyshau 为此功能做出贡献。