Deno 1.45: 工作区和单仓库支持
Deno 继续发展,发布了 Deno 1.45。此版本最突出的功能是引入了工作区,为管理单仓库提供了强大的解决方案。此新增功能简化了大型代码库中的依赖项管理、配置共享和模块组织。除了工作区之外,此更新还包括对 Node.js 兼容性的改进、对 `deno install` 的更新、新的 `deno init --lib` 命令、`deno vendor` 的弃用等等。
要升级到 Deno 1.45,请在您的终端中运行以下命令
deno upgrade
如果 Deno 尚未安装,请运行以下命令之一进行安装,或点击此处了解如何安装。
# Using Homebrew (macOS):
brew install 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.45 中的新增功能
- 工作区支持
- Node.js 兼容性改进
- 冻结锁文件
deno install
更新deno init --lib
deno vendor
现已弃用deno test
文件发现- Jupyter 笔记本改进
deno compile
支持 `--env` 标志- 更灵活的语言服务器
- 标准库更接近稳定版
- V8 12.7 和 TypeScript 5.5.2
- 使用 `DENO_FUTURE=1` 试用 Deno 2 的功能
- 鸣谢
工作区支持
Deno v1.45 添加了对工作区和单仓库的支持。支持两种工作区形式:在 `deno.json` 中定义的 Deno 首选工作区和向后兼容的 npm 工作区。
Deno 工作区非常简单。全局定义的配置将应用于每个成员包,但可以被成员包覆盖。您可以混合使用 npm 和 Deno 工作区,例如 Deno 工作区中的 npm 包或反之亦然。
将工作区成员发布到 JSR 非常简单,只需运行 `deno publish` 即可。 标准库 是有效使用工作区的良好示例。
要开始使用,请在您的 `deno.json` 中定义一个 `"workspace"` 元素,并列出成员目录。
{
"workspace": ["./add", "./subtract"]
}
npm
工作区 在 Deno 中也可以无缝使用。无论您是在更大的 npm 工作区中包含 Deno 库,还是在更大的 Deno 工作区中包含 npm 库,依赖项都将正确解析。
要详细了解工作区支持,请访问Deno 文档。
我们还将在 7 月 16 日星期二太平洋时间上午 9 点(UTC-7)举办一场YouTube 上为期一小时的直播,详细介绍我们的新工作区支持并回答您的问题。 点击此处报名。
Node.js 兼容性改进
Node-API 支持已完全更新,修复了 `prisma`、`sqlite3`、`paper`、`duckdb`、`nodejs-polars` 等软件包中存在的许多问题。
其他 Node.js 兼容性改进包括
我们正在努力支持 dd-trace。它还没有完全实现,但我们正在接近目标
- 添加了`net.BlockList` 和 `net.SocketAddress`
- 在`node:diagnostics_channel` 模块 中添加了缺失的 API
- 支持 `Module.parent`
`fs.lutimes` 和 `fs.lutimesSync` 现在已受支持,[
fs.lchown
和process.getegid
] (https://github.com/denoland/deno/pull/24418) 也是如此已添加了 `node:crypto` 和 `node:zlib` 常量 添加
在 `node:fs` 中,`Dirent.path` 和 `Dirent.parentPath` 现在可用
`node:http` 模块收到了重大更新
Server#close()
现在执行优雅关闭,允许正在处理的请求完成- 已添加了 `ServerResponse#appendHeader()` 添加
- 现在支持所有 `ServerResponse#writeHead()` 签名
ServerResponse#setHeaders
现在可以处理标题数组ServerResponse
正确处理分块写入ServerResponse
在流式传输时不会导致进程崩溃Server
如果尚未开始监听,则为 `address` 返回 `null`ClientRequest
现在可以正确发送请求
`node:vm` 将消耗更少的内存
crypto.Hash
实现已更新@grpc/grpc-js
支持现在更加健壮,正确设置了 `end_stream` 标志`node:child_process` API 现在支持 `stdio` 选项的 `"ipc"` 值
`readline/promises` 模块 现在可在 ES 模块中使用
此外,还有其他与 `npm` 支持相关的改进
- Deno 将发现放在您的主目录中的 `npmrc` 配置文件,以更好地支持私有注册表
- 与软件包一起提供的类型现在优先于 `@types` 范围内的类型
- Deno 现在支持更多形式的 SemVer 约束
冻结锁文件
添加了一个新的 `--frozen`(别名 `--frozen-lockfile`)标志,用于控制锁文件的行为。
您可以使用此标志告诉 Deno 在锁文件过时时始终报错。这在 CI 管道中特别有用,您应该确保所有推送的代码都是最新的,并且依赖项没有新的或意外的更改。
在使用 `--frozen` 标志运行 deno 命令时,任何尝试使用新内容更新锁文件的行为都将导致命令退出,并显示将进行的修改所导致的错误。
例如,假设您的项目中某个地方导入的是 `npm:[email protected]`。之后,某人从略微过时的 AI 聊天机器人中复制了一段代码,该聊天机器人只知道 chalk 版本 `5.2.0`,因此某个文件中最终会有一个类似以下的导入
import chalk from "npm:[email protected]";
幸运的是,您的 CI 管道有一个使用 `--frozen` 指定的测试步骤
deno test --frozen --coverage
它不会静默地将 chalk 的第二个(过时的)版本添加到您的依赖项树中,而是会失败,并显示将 chalk 5.3.0 添加到您的锁文件中
error: The lockfile is out of date. Run `deno cache --frozen=false` or rerun with `--frozen=false` to update it.
changes:
5 | - "npm:[email protected]": "npm:[email protected]"
6 | - },
7 | - "npm": {
5 | + "npm:[email protected]": "npm:[email protected]",
6 | + "npm:[email protected]": "npm:[email protected]"
7 | + },
8 | + "npm": {
9 | + "[email protected]": {
10 | + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
11 | + "dependencies": {}
12 | + },
如果您打算显式更新您的锁文件,您可以指定 `--frozen=false`,这将在没有错误的情况下更新锁文件。
使用上述设置,每次依赖项更新都需要运行使用 `--frozen=false` 标志的命令或任务,从而使这些更新成为有意且明确的操作。
最后,`--lock-write` 现在已弃用,将在 Deno 2 中删除。您可以将 `--lock-write` 的用法替换为 `--frozen=false`。
deno install
更新
在 Deno 2 中,deno install
子命令的行为将更像 npm install
以支持常见的开发流程。目前在 Deno 中,deno install <pkg>
会全局安装二进制包。在 Deno 2 中,deno install <pkg>
默认情况下会本地安装包,将新的依赖项添加到项目中(类似于 deno add <pkg>
)并进行缓存。此外,deno install
不带参数将缓存 package.json
或导入映射中列出的本地依赖项,并设置一个本地 node_modules
目录(如果适用)。要全局安装,您需要指定 --global
(-g
) 标志:deno install --global <pkg>
。
要在您的项目中试用新的安装命令,请使用 DENO_FUTURE=1
运行
DENO_FUTURE=1 deno install
带有参数,类似于 deno add
DENO_FUTURE=1 deno install @david/dax
我们鼓励您尝试新的 deno install
并报告您遇到的任何问题!
npm 生命周期脚本支持
package.json
中的某些脚本是特殊的,因为它们在某些操作时会由 npm
自动执行。npm
支持许多生命周期脚本,但作为包的使用者,主要的相关脚本是预安装/后安装脚本,它们在安装包时执行(即通常在 npm install
期间)。
一些包依赖于它们的安装脚本执行设置步骤(例如,下载或构建原生插件的工件),如果它们没有执行,则无法正常工作。以前,Deno 不支持执行生命周期脚本,因此这可能会导致在使用某些包时出现令人困惑的错误,而且没有简单的解决方案。
现在,Deno 支持在 deno cache
(以及 DENO_FUTURE=1 deno install
)中运行生命周期脚本,如果它检测到包具有未运行的生命周期脚本,则会发出警告。
通过使用 deno cache
(或 DENO_FUTURE=1 deno install
)指定 --allow-scripts
标志,您可以选择为特定包运行生命周期脚本
deno cache --allow-scripts=npm:duckdb main.ts
ℹ️ 注意
目前,我们只支持在使用本地node_modules
目录(deno.json
中的"nodeModulesDir": true
)时使用生命周期脚本。
将来,我们计划添加对没有node_modules
的生命周期脚本的支持,但这将是尽力而为的,因为某些包依赖于位于node_modules
目录中。
deno init --lib
- 轻松设置新的库
deno init
子命令在 Deno v1.25 中引入,允许您用几个按键启动 Deno 项目的最小脚手架。
自从 JSR 引入以来,用户一直在要求一种快速启动将发布到 JSR 的项目的方法。
您只需使用 Deno v1.45 和 deno init --lib
即可做到这一点
✅ Project initialized
Run these commands to get started
# Run the tests
deno test
# Run the tests and watch for file changes
deno task dev
# Publish to JSR (dry run)
deno publish --dry-run
只需确保在发布之前更新生成的 deno.json
文件中的 name
和 version
字段!
deno vendor
现已弃用
deno vendor
在 Deno v1.19 中添加 以允许用户将所有依赖项都放入项目目录中。
此后,另一种依赖项引入方式 在 Deno v1.37 中引入,使用 --vendor
标志或配置文件中的 { "vendor": true }
选项。
此选项获得了许多正面反馈,并指出了 deno vendor
子命令的缺点和糟糕的开发体验。考虑到这一点,deno vendor
现在已弃用,并计划在 Deno 2 中删除。
请迁移到使用配置文件中的 --vendor
标志或 vendor
选项。
deno test
文件发现
deno test
可以自动发现并运行与特定模式匹配的文件的测试
- 文件名以
_test
结尾 - 例如app_test.ts
、component_test.tsx
- 文件名以
.test
结尾 - 例如router.test.ts
、controller.test.js
- 文件名是
test
- 例如test.ts
、test.js
为了提高与更广泛生态系统的兼容性,deno test
现在将自动发现并运行位于 __tests__
目录下的文件
$ tree
.
├── __tests__
│ ├── integration.ts
│ └── unit.ts
└── main.ts
2 directories, 3 files
在 Deno v1.44 中
$ deno test
error: No test modules found
在 Deno v1.45 中
$ deno test
deno test
Check file:///Users/ib/dev/test_discovery/__tests__/integration.ts
Check file:///Users/ib/dev/test_discovery/__tests__/unit.ts
running 1 test from ./__tests__/integration.ts
integration test ... ok (0ms)
running 1 test from ./__tests__/unit.ts
unit test ... ok (0ms)
ok | 2 passed | 0 failed (11ms)
Blob.bytes()
继 Deno v1.44 中的更改 以及 Web 文件 API 规范的更新之后,现在支持 Blob.bytes()
const jsonStr = JSON.stringify({ hello: "world" }, null, 2);
// Before:
const blob = new Blob([jsonStr], { type: "application/json" });
const buffer = new Uint8Array(await blob.arrayBuffer());
// After:
const blob = new Blob([jsonStr], { type: "application/json" });
const buffer = await blob.bytes();
Jupyter 笔记本改进
您现在可以在 Jupyter 笔记本中使用 prompt
和 confirm
API 来提供更多灵活性和交互性。
为了进一步改善 JavaScript(和 TypeScript)的数据科学生态系统,我们计划在下一个版本中添加使用 JSX 和 React 的交互式小部件支持。
deno compile
支持 --env
标志
--env
标志 在 Deno v1.38 中添加,添加了从 .env
文件加载进程的环境变量的原生支持。
使用 Deno v1.45,--env
标志可用于将某些环境变量包含到使用 deno compile
生成的二进制文件中。
🛑 注意
请记住,这些环境变量仍然可以在检查发布的程序的内容时读取,因此请谨慎使用此功能。将写入二进制文件的生产密钥发布可能不是最好的主意。
在执行使用 deno compile
创建的程序时,对 .env
文件中提供的变量的所有对 Deno.env.get(<var_name>)
的调用将返回编译过程中指定的 value,而不是用户系统上的当前变量
$ cat .env
HELLO_THERE=deno
$ cat main.ts
console.log("Hello there")
console.log(Deno.env.get("HELLO_THERE") + "!");
$ deno compile --env --allow-env main.ts
...
在 Deno v1.44.4 中
HELLO_THERE="General Kenobi" ./main
Hello there
General Kenobi!
在 Deno v1.45.0 中
HELLO_THERE="General Kenobi" ./main
Hello there
Deno!
更灵活的语言服务器
以前,VSCode 扩展只能读取并合并位于工作区根目录的 deno.json
或 deno.jsonc
文件。来自那里的配置将应用于每个打开的源文件。这使得某些 monorepo 配置变得不可能。
1.45 使语言服务器更加独立于编辑器中打开的根文件夹。子目录中的配置文件现在会被检测到,即使存在多个配置文件也是如此。每个发现的 deno.json
或 deno.jsonc
将产生一个单独的范围,具有自己的类型检查环境、模块解析等等。您可以为 compilerOptions.libs
配置不同的条目,或导入模块,这些模块将对全局类型进行扩展,这些扩展不会污染其他 deno.json[c]
范围的环境。
标准库更接近稳定
Deno 标准库 提供了一组由核心团队审核的优质包,并保证与 Deno 协同工作。
正如我们之前博客文章中所述,标准库目前正在进行稳定工作,目标是稳定 38 个包中的 31 个。
迄今为止,我们已经稳定了 13 个包
@std/assert
@std/bytes
@std/collections
@std/crypto
@std/data-structures
@std/encoding
@std/html
@std/media-types
@std/msgpack
@std/path
@std/regexp
@std/toml
@std/uuid
这些包已达到 1.0.0 版本,遵循 SemVer 语义 并确保它们在 1.x.x 版本中的兼容性。
剩余的 18 个包已发布了它们的发布候选版 (RC) 版本(请参阅路线图问题 获取列表)。如果您目前正在使用任何这些包,请考虑测试 RC 版本并与我们分享您的反馈!
有关稳定时间线的更多详细信息,请参阅路线图问题。
V8 12.7 和 TypeScript 5.5.2
Deno 1.45 带有 V8 12.7 和 TypeScript 5.5.2。
DENO_FUTURE=1
尝试 Deno 2 的功能
使用 我们建议您尝试使用 DENO_FUTURE=1
环境变量运行现有的项目,该变量将启用 Deno 2 的功能。我们预计迁移工作量很小或非常低。如果您的体验不同,请 与我们分享。
致谢
没有社区的帮助,我们无法构建 Deno!无论是通过在我们的社区 Discord 服务器 中回答问题,还是 报告错误,我们都非常感谢您的支持。特别感谢以下人员对 Deno 1.45 的贡献:Adam Gregory、Andreas Kohn、Andrew Johnston、Filip Skokan、HasanAlrimawi、Kenta Moriuchi、Luca Bruno、Oliver Medhurst、Richard Carson、Tom Alcorn、Victor Turansky、Yazan AbdAl-Rahman、Zander Hill、Zebreus、muddlebee、safaa-mojahed、ud2。
您想加入 Deno 贡献者的行列吗? 在此查看我们的贡献文档,我们下次在列表中见。
信不信由你,上面列出的更改仍然没有告诉你 1.45 中所有改进的地方。您可以在 GitHub 上查看 Deno 1.45 中合并的完整拉取请求列表。
感谢您关注我们的 1.45 版本,希望您喜欢用 Deno 构建!