Deno 1.46:最后一个 1.x 版本
Deno 的目标是提升人们编写 JavaScript 的方式,通过提供 原生 TypeScript 支持、一体化工具链、Web 标准 API 支持 以及 默认安全的代码执行
Deno 1.46(我们最终的 1.x 版本)继续朝着这一愿景前进,通过 简化 CLI,实现 更短的调用方式 和 简短的权限标志,启用 使用 deno serve --parallel
的多线程 Web 服务器,并添加了众多 Node.js/npm 兼容性改进(包括对 playwright
、@google-cloud
、mysql2
、pglite
、ssh2
等的支持)。
除了这些突出的更新,1.46 还带来了 更好的依赖管理(使用 deno remove
和 deno clean
)、用于 deno compile
的代码签名,以提高软件可移植性,以及新添加的 对 deno fmt
中 HTML、CSS、YAML 等的支持。
要升级到 Deno 1.46,请在您的终端中运行以下命令
deno upgrade
如果 Deno 尚未安装,请运行以下命令之一进行安装,或者 在此处了解如何安装。
# Using Shell (macOS and Linux):
curl -fsSL https://deno.land/install.sh | sh
# Using PowerShell (Windows):
iwr https://deno.land/install.ps1 -useb | iex
Deno 1.46 的新功能
- 更简单的 CLI
- 更快的
deno serve
deno fmt
现在支持 HTML、CSS、YAML 等- 依赖管理
- 用于
deno compile
的代码签名 deno upgrade
改进- Node.js 和 npm 兼容性
- 性能改进
- 测试和覆盖率改进
- 更简单的冻结锁定文件
- 文件观察器
- 两个新的 Web API
- 标准库是稳定的
- V8 12.9
- 致谢
- 下一步是什么?
更简单的 CLI
此版本对 deno
CLI 进行了重大更新。
更短的调用方式
此版本带来了一个长期以来用户一直要求和期待的更改,即运行 Deno 程序的方式。
deno
和 deno run
已更改,为执行常见任务提供了更符合人体工程学的方式。
您现在只需使用 deno
即可运行程序,无需再指定 run
子命令
# Deno v1.45
deno run hello.ts
Hello world 🦕
# Deno v1.46
deno hello.ts
Hello world 🦕
您仍然可以将所有必要的标志传递给 deno
子命令
# Deno v1.45
deno run --allow-read main.ts
Reading ./log.txt...
# Deno v1.46
deno --allow-read hello.ts
Reading ./log.txt...
另一个符合人体工程学的设计是使用 deno run
运行任务的能力
// deno.json
{
"tasks": {
"test": "deno test --allow-read --allow-net"
}
}
# Deno v1.45
deno task test
# Deno v1.46
deno run test
这可能是一个微小的改变,但肌肉记忆是真实存在的!对于那些多年来一直使用 npm run <script>
运行任务的用户来说,这将是一个改变游戏规则的设计。
⚠️ v1.45 之前的行为仍然受支持。您仍然可以使用
deno task
和deno run
,就像在以前的版本中一样。这些更改是为了那些习惯于将第一个参数作为脚本执行的其他脚本环境的用户而设计的。
简短的权限标志
Deno 的权限系统是 Deno 附带的最重要功能之一。--allow-*
和 --deny-*
标志对于限制对系统部分的访问很有用。由于它们的冗长性,许多用户选择使用 --allow-all
标志,或者更准确地说,是它的简写形式 -A
。
在 Deno v1.46 中,您现在可以使用大多数常用权限标志的单字母变体
长 | 短 |
---|---|
--allow-read |
-R |
--allow-write |
-W |
--allow-env |
-E |
--allow-net |
-N |
--allow-sys |
-S |
这些简写标志接受允许列表,就像长版本一样 - 例如 -R=./static
、-E=DEBUG,LOG
、-N=deno.com
。
如果您不想提供允许列表,可以将它们组合在一起 - 例如 -RWN
将启用 read
、write
和 net
权限。
以下是一些关于如何缩短 CLI 调用方式的示例
# Deno v1.45
deno run --allow-read=./static --allow-env --allow-net=myapi.example.com main.ts
# Deno v1.46
deno run -R=./static -E -N=myapi.example.com main.ts
# Deno v1.46 without `run` subcommand
deno -R=./static -E -N=myapi.example.com main.ts
# Deno v1.45
deno run --allow-read --allow-write --allow-env --allow-sys main.ts
# Deno v1.46
deno run -RWES main.ts
# Deno v1.46 without `run` subcommand
deno -RWES main.ts
新的帮助输出
CLI 选项标志现在按类别逻辑分组
权限提示链接到文档
权限提示现在链接到与相关权限标志相关的文档
deno help <subcommand>
--allow-*
标志帮助输出
权限标志的帮助文本已更新,包括示例用法。
--env
重命名为 --env-file
--env
标志提供“dotenv”功能,该功能从指定的文件中读取环境变量,并在执行 JavaScript 代码之前为进程设置它们。它非常方便,所有流行的 JS 运行时都提供了此功能。为了与其他运行时保持一致并便于迁移,--env
标志已重命名为 --env-file
。旧的标志将继续起作用,但不会在帮助输出中显示。
新的进度条
一直以来,我们收到的反馈是,Deno 有时看起来卡住了,无法下载依赖项。实际上,问题很多 - 网络连接不佳、包注册表限制速率等等。也就是说,没有交互式指示来表明 Deno 正在执行某些任务,这对那些急于开始编写代码的用户来说没有帮助。
为了明确地表明 Deno 仍在工作,我们更新了进度条,以提供更多交互性
deno check
和 deno cache
命令参数中的通配符支持
Deno v1.34 在配置文件和 CLI 标记中添加了对通配符的支持。此通配符功能已扩展到大多数 Deno 子命令,现在您可以在 deno check
和 deno cache
子命令中享受通配符扩展。
⚠️ 确保将通配符放在引号中。 否则您的 shell 将扩展它而不是 Deno,这可能会导致由于通配符实现差异而产生的细微错误。
# Type-check all `.ts` files in the current directory and its descendants
deno check "*/**/*.ts"
# Cache all JS files in the current directory
deno cache "*.js"
deno serve
更快的 deno serve
在 Deno v1.43 中引入,并收到了很多正面反馈。此版本为 deno serve
带来了几个非常受欢迎的更改。
1. 开发
通过添加 deno init --serve
选项,您可以在 10 秒内启动服务器。
示例项目包括使用 @std/http
进行路由,以及集成的文件服务器以高效地提供静态资源。
$ deno init --serve
$ deno serve -R main.ts
Listening on https://127.0.0.1:8000
$ curl https://127.0.0.1:8000/hello
此子命令旨在成为一个快速的原型工具,您可以随着项目的增长而扩展它,它并不意味着要取代像 Fresh 这样的框架。
2. 类型检查
deno serve
的局限性之一是它复杂的设置才能正确地类型检查入口文件。使用 Deno v1.46 和最新的 TypeScript 功能,这现在变得容易了:只需在入口文件的 default export
中添加 satisfies Deno.ServeDefaultExport
// server.ts
export default {
fetch(req) {
console.log(req.RequestDoesntHaveThisPropery);
return new Response("Hello world!");
},
} satisfies Deno.ServeDefaultExport;
如果您对该文件进行类型检查,Deno 会警告任何 API 兼容性问题。
$ deno check server.ts
Check file:///dev/server.ts
error: TS2339 [ERROR]: Property 'RequestDoesntHaveThisPropery' does not exist on type 'Request'.
console.log(req.RequestDoesntHaveThisPropery);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at file:///dev/server.ts:3:21
请注意,当您构建新的服务器项目时,deno init --serve
会自动将 satisfies Deno.ServeDefaultExport
添加到您的 deno serve
入口点。
3. 扩展
为 deno serve
子命令提供支持的 Deno.serve()
API 非常快。但它默认只使用一个线程。这是有道理的,因为 JavaScript 是一种单线程语言,前提是您不使用像 new Worker()
这样的 API。但是现代服务器拥有多个核心,应该利用它们来实现资源的最有效利用。
为了帮助您在可用资源的基础上实现最佳性能,deno serve
现在支持 --parallel
标记,它允许您通过利用 CPU 的多个核心在多个线程上运行服务器。
$ deno serve --parallel main.ts
deno serve: Listening on http://0.0.0.0:8000 with 10 threads
您可以使用 DENO_JOBS
环境变量指定要使用的线程数量。如果您没有指定此变量,它将默认为机器提供的线程数量。例如,要将线程数限制为 4,您可以运行
$ DENO_JOBS=4 deno serve --parallel main.ts
deno serve: Listening on Listening on http://0.0.0.0:8000 with 4 threads
这里没有魔法——Deno 只是运行 X 个相同的服务器副本,让每个线程成为一个单线程的 JavaScript 运行时。这使得推理应用程序的状态变得更加简单,因为本地扩展的行为与云中扩展的行为相同。
了解更多关于此功能是如何工作的,请查看 关于并行化 deno serve
的 Deno 演讲。
deno fmt
现在支持 HTML、CSS、YAML 等等
此版本对 Deno 内置格式化程序 deno fmt
进行了重大升级。
deno fmt
现在可以用于格式化 HTML、CSS、SCSS、Sass、Less、YAML、Astro、Angular、Svelte 和 Vue 文件。
让我们格式化此 HTML 文件
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello `deno fmt`</title>
</head>
<body>
<h1>Hello <pre>
deno fmt!
</pre></h1>
</body></html>
$ deno fmt --unstable-html index.html
$ cat index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Hello `deno fmt`</title>
</head>
<body>
<h1>Hello <pre>
deno fmt!
</pre></h1>
</body>
</html>
由于这是对 deno fmt
的重大更改,因此在这些新格式中的格式化目前尚不稳定。为了在 deno fmt
中启用这些新格式,需要传递 --unstable-*
标记或在 deno.json(c)
文件中添加选项。请注意,当启用这些选项时,deno fmt
会自动拾取相应的文件。
使用 CLI
# format HTML
$ deno fmt --unstable-html index.html
# format CSS/SCSS/Sass/Less
$ deno fmt --unstable-css styles.css
# format YAML
$ deno fmt --unstable-yaml config.yml
# format component files
$ deno fmt --unstable-component App.vue App.svelte
使用配置文件
// deno.json
{
"unstable": [
"fmt-html",
"fmt-css",
"fmt-yaml",
"fmt-component"
]
}
$ deno fmt index.html styles.css config.yml App.vue App.svelte
非常感谢 Pig Fang 提供这些格式化程序!
导入断言已弃用
Deno 在 v1 中附带了导入断言提案,允许您导入 JSON 文件
// main.js
import data from "./data.json" assert { type: "json" };
console.log(data);
此后,该提案经历了重大变化,包括将关键字从 assert
更新为 with
,并更名为 导入属性。
在 Deno 2 中,将不再支持导入断言。为了帮助您迁移到导入属性,从 Deno v1.46 开始,将为每次使用 assert
关键字打印警告,该关键字应替换为 with
关键字。
// data.json
{
"deno": "2"
}
$ deno run main.js
⚠️ Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword.
import data from "./data.json" assert { type: "json" };
at file:///dev/main.js:1:31
{ deno: "2" }
让我们将 assert
更改为 with
// main.js
import data from "./data.json" with { type: "json" };
console.log(data);
$ deno run main.js
{ deno: "2" }
依赖项管理
Deno v1.46 带来了对依赖项管理的几项改进。
deno add
现在支持 dist
标记并建议 npm
包
您现在可以在添加 npm
依赖项时使用 dist
标记,例如使用 deno add npm:ajv@latest
来拉取 ajv
包 的 latest
标记。
此外,当您尝试添加仅在 npm
上可用的 JSR 包时,deno add
现在将提供一个有用的消息。
$ deno add ajv
error: jsr:ajv was not found, but a matching npm package exists. Did you mean `deno add npm:ajv`?
deno remove
根据大家的要求,deno
现在拥有一个子命令来从您的配置文件和锁文件中删除依赖项。
$ deno remove @std/assert @std/path
Removed @std/assert
Removed @std/path
请记住,这些包仍将保留在全局缓存中以备将来使用。如果您想彻底清理环境,请查看 deno clean
。
deno clean
Deno 拥有一个全局缓存,您可以使用 DENO_DIR
环境变量 来控制它。此缓存用于存储远程依赖项,以便在多个项目中高效使用,V8 代码缓存以加快启动速度,以及用于子命令(如 deno fmt
、deno lint
等)的缓存,以最大限度地减少每次运行时完成的工作。
现在您可以通过调用 `deno clean` 快速清除整个缓存。
为 `deno compile` 代码签名
由 `deno compile` 生成的程序现在可以进行代码签名。
deno compile app.ts
# on macOS use `codesign` tool
codesign --sign ./app
# on Windows use `signtool`
signtool sign /fd SHA256 .\app.exe
除此之外,为 Windows 编译的程序可以拥有自定义图标。
deno compile --icon=./icon.ico game.tsx
最后,权限提示已调整,以便在遇到缺少权限时提供更有帮助的错误消息。
// app.js
console.log(Deno.readTextFileSync("./log.txt"));
# compile with no permissions
deno compile ./app.js
./app
Requires read access to ./log.txt, specify the required permissions during compilation using `deno compile --allow-read`
# compile again with suggested permissions
deno compile --allow-read ./app.js
./app
Hello world!
在 关于 `deno compile` 的 Deno 演讲 中了解有关此最新更新的更多信息。
`deno publish` 帮助确保包已获许可
为了确保包已正确获得许可,`deno publish` 现在在发布包时需要许可字段和/或文件。
> deno publish
error[missing-license]: missing license field or file
--> deno.json
= hint: add a "license" field. Alternatively, add a LICENSE file to the package and ensure it is not ignored from being published
docs: https://jsr.deno.org.cn/go/missing-license
error: Found 1 problem
要解决此问题,请在您的 deno.json 或 jsr.json 文件中添加 `"license"` 字段。
{
"name": "@deno/add",
"version": "1.0.0",
"license": "MIT", // add this and/or include a LICENSE file
"exports": "./mod.ts"
}
`deno upgrade` 改进
`deno upgrade` 是一个便捷的方式,可以让你及时使用 Deno 的最新版本或“canary”版本。
此版本使它更加方便,一旦你升级到 Deno v1.46.0,你就可以舍弃任何 CLI 标志,转而使用
# upgrade to latest stable release
$ deno upgrade
# upgrade to a specific version
$ deno upgrade v1.46.0
# upgrade to latest canary release
$ deno upgrade canary
# upgrade to a specific release
$ deno upgrade 526f39fbb9dacce12c69d24a55798d0bde8f2707
此外,我们添加了一个新的发布频道:发布候选频道。我们打算在发布 Deno 2 之前提供多个发布候选版本。
你可以通过运行以下命令来试用它:`deno upgrade rc`,但请注意,目前只有 v1.46.0 发布候选版本可用。
请关注我们的 Twitter 帐户,获取有关 Deno 2 发布候选版本的消息。
Node.js 和 npm 兼容性
此版本在 Deno 与 Node.js 和 npm 包的兼容性方面带来了许多改进。本周期专注于让几个很受欢迎的包正常工作,这些包是大家强烈要求的。
playwright
现在在 Linux 和 macOS 上受支持,这得益于 `node:child_process` API 中改进的管道支持- 许多 `node:crypto` API 已被重写,修复了大量错误并支持多个包(例如 `ssh2`)。
- 添加了 `CipherIv.setAutoPadding()`,修复了 `ethereum-cryptography`
- `crypto.diffieHellman` 现在可用。
- `crypto.randomFillSync()` 尊重偏移量。
- 对加密密钥的处理 已彻底改造,增加了对以下密钥的支持:PKCS#1、PKCS#8、RSA-PSS、X25519、ED25519、DH 等等。
- 支持 `ieee-p1363` ECDSA 签名。
- `crypto.createPublicKey()` 使用 PEM 私钥
- 还有更多…
- 现在支持 `@google-cloud` 包,这得益于 对 `Http2Session.socket` 的支持
- `npm:bindings` 和 `npm:callsites` 包可以正常工作,因为修复了 `Error.prepareStackTrace` API
- 现在支持 `fsevent` 模块,该模块已获得支持
vitest
的兼容性正在不断向前发展,这得益于- `node:inspector` 现在可用
- `node:inspector#Session` 构造函数不再抛出异常
yoctocolors
现在可以正常工作,这得益于 修复了 `tty.WriteStream.hasColor` 和 支持 `tty.hasColors()` 和 `tty.getColorDepth()`- 现在支持 `util.debug`。
chokidar
现在更加可靠,这得益于 Windows 上的声明修复mongodb
更加稳定,这得益于 `net.Socket` API 中的修复 和 `node:http` 中的另一个修复- 现在支持 `mysql2` 包。
- `node:vm` 收到了 另一个主要改造
- `size-limit` 可以正常工作,这得益于 对 `node:zlib` 模块的更佳覆盖范围
- `aws-sdk` 更加可靠,这得益于 对子数组的更佳处理
- `ecmarkup` 现在可以正常工作。
- `pglite` 现在已完全 支持
- `grpc-js` 应该更加可靠,这得益于 释放流容量
- `paper-js` 或 `prismjs` 的支持更加完善,这得益于 修复了暴露给 npm 包的全局变量
- `fs.exist` 和 `fs.existSync` 已优化
- `shelljs` 现在可以 使用 `npm:` 说明符
- 从字符串转换时,`Buffer` 的 性能得到了提升
对 Node.js 和 npm 支持的其他更改包括
`。npmrc` 文件现在 支持 `username` 和 `_password` 选项
使用 Node.js 全局变量,而不导入它们 会生成 lint 警告。提供了补充的快速修复操作。
性能改进
Deno v1.46 带来了几个性能改进。
- `Deno.serve()` API 的速度提高了 8-15%
- `crypto.randomUUID()` 现在快了 5 倍
- `Response.clone()` 快了 80%
- `deno doc` 进行了一些优化,以改善内存使用情况。
测试和覆盖率改进
此版本对 `deno test` 和 `deno coverage` 做了以下改进。
- `deno coverage --html` 现在显示面包屑,方便导航。
`deno test` 获得了一个新的 `--hide-stacktraces` 标志,它将在测试失败时禁用打印错误堆栈跟踪。
`deno test` 中的 `--allow-none` 标志已重命名为 `--permit-no-files`。我们打算在 Deno 2 中弃用旧标志,因此,如果你依赖它,请确保更新你的脚本!
更简单的冻结锁定文件
Deno v1.46 中引入的冻结锁定文件 是一种简单方便的方式,可以确保 Deno 在向锁定文件添加新依赖项时出错。
此版本使确保项目中的每个人都使用此选项变得更容易,方法是在配置文件中指定以下内容
{
"lock": {
"frozen": true
}
}
任何时候更新依赖项,这将更改锁定文件,Deno 将抛出错误,要求你显式传递 `--frozen=false` 标志,使添加依赖项成为你端的一个有意识的决定。
此外,为了节省带宽和检查 `git diff` 所需的时间,锁定文件格式将在 Deno 2 中变得更加简洁。
你可以使用 `DENO_FUTURE=1` 环境变量来试用它。但是,请注意,切换回不使用 `DENO_FUTURE` 将需要重新生成锁定文件。
文件监视器
热模块替换,在 Deno v1.38 中添加, 现在在 --watch-hmr
标志下被认为是稳定的。 它将出现在相关子命令的帮助输出中 --watch
标志旁边。
此外 deno test
获得了对 --watch=<PATHS>
标志的支持,它允许您传递额外的文件路径以供监视更改并触发测试重新运行。
Web APIs
Deno v1.46 为 Web APIs 带来了两个显著的补充
AsyncIterable<T>
现在可以用来构建Request
和Response
类的主体。 例如,来自node:fs
的createReadStream
是一个实现了AsyncIterable
协议的 API,因此它可以与fetch
API 一起使用,如下所示
const file = createReadStream("./fixture.json");
const response = await fetch("http://example.com", {
method: "POST",
body: file,
});
Deno 现在将随着数据的可用(从磁盘读取)而流式传输数据,以实现高效的 HTTP 调用。
URLPattern
API 现在支持ignoreCase
和hasRegExpGroups
。 前者允许不区分大小写的模式匹配
const pattern = new URLPattern({
pathname: "/foo/bar",
}, {
ignoreCase: true,
});
pattern.test("/foo/bar"); // true
pattern.test("/fOo/BaR"); // true
hasRegExpGroups
属性可以让您知道模式是否使用任何正则表达式组
const pattern = new URLPattern({
pathname: "/foo/bar/(.+)",
});
pattern.hasRegExpGroups; // true
标准库是稳定的
Deno 标准库 提供了一套高质量的包,涵盖数据解析和操作、使用网络协议以及核心团队审核并保证与 Deno 兼容的一般实用程序。
我们很高兴地宣布我们已经完成了 我们的稳定过程,有 30 个包达到 v1 或更高版本。
- std/assert
- std/async
- std/bytes
- std/cli
- std/collections
- std/crypto
- std/csv
- std/data-structures
- std/encoding
- std/expect
- std/fmt
- std/front-matter
- std/fs
- std/html
- std/http
- std/json
- std/jsonc
- std/media-types
- std/msgpack
- std/net
- std/path
- std/regexp
- std/semver
- std/streams
- std/testing
- std/text
- std/toml
- std/ulid
- std/uuid
- std/yaml
为了分享使用标准库中的模块可以做些什么,我们发布了 一条推文串,每条推文包含一个模块的代码示例。
如果您想了解更多关于我们的标准库的信息,请查看我们的 3 分钟短片
V8 12.9
Deno 1.46 附带最新的 V8 12.9。
鸣谢
没有我们社区的帮助,我们无法构建 Deno! 无论是在我们的社区 Discord 服务器 上回答问题,还是 报告错误,我们都非常感谢您的支持。 特别感谢以下人员对 Deno 1.46 的贡献:Andreas Deininger、Bedis Nbiba、Birk Skyum、Hajime-san、HasanAlrimawi、Ian Bull、Igor Borisoglebski、Ivancing、Kenta Moriuchi、Kyle Kelley、MrEconomical、MujahedSafaa、Pig Fang、Rano | Ranadeep、Roy Ivy III、Sean McArthur、Yazan AbdAl-Rahman、Zebreus、chirsz、i-api、melbourne2991、seb、vwh 和 Łukasz Czerniawski。
您想加入 Deno 贡献者的行列吗? 查看我们的贡献文档,下次您就会出现在列表中。
信不信由你,上面列出的更改仍然没有告诉你 1.46 中变得更好的所有内容。 你可以查看在 Deno 1.46 中合并的完整拉取请求列表 在 GitHub 上。
感谢您关注我们的 1.46 版本发布,我们希望您喜欢使用 Deno 进行构建!
接下来是什么?
🚨️ Deno 2 即将发布 🚨️
几天后,Deno 2 的第一个“发布候选版本”将发布。
Deno 2 中有一些 轻微的重大更改。
您可以使用 deno upgrade rc
获取它,但您现在就可以通过添加 DENO_FUTURE=1
环境变量来防范您的代码。