跳到主要内容
Deno 2.4 现已发布,包含 deno bundle、字节/文本导入、OTel 稳定版等功能
了解更多
Deno 1.45

Deno 1.45:工作区和 Monorepo 支持

Deno 1.45 发布,Deno 持续进化。此版本最突出的功能是引入了工作区(workspaces),为管理单体仓库(monorepos)提供了强大的解决方案。这一新增功能简化了大型代码库的依赖管理、配置共享和模块组织。除了工作区,本次更新还包括对 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 中的新特性

工作区支持

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 文档

我们还将于太平洋时间(UTC-7)7月16日星期二上午9点在 YouTube 上举办一场一小时的直播,详细介绍我们的新工作区支持并回答您的问题。在此处报名

Node.js 兼容性改进

Node-API 支持已全面改进,修复了 `prisma`、`sqlite3`、`paper`、`duckdb`、`nodejs-polars` 等软件包的许多现有问题。

其他 Node.js 兼容性改进包括

此外,还有其他与 npm 支持相关的改进

冻结锁文件

已新增一个 `--frozen`(别名为 `--frozen-lockfile`)标志,用于控制锁文件的行为。

您可以使用此标志,在锁文件过时时让 Deno 报错。这在 CI 流水线中特别有用,您可以确保所有推送的代码都是最新的,并且依赖项没有新的或意外的更改。

当使用 `--frozen` 标志运行 Deno 命令时,任何尝试使用新内容更新锁文件的操作都将导致命令退出并显示错误,其中包含本应进行的修改。

例如,假设您的项目中某个地方导入了 `npm:chalk@5.3.0`。后来,有人从一个稍旧的、只知道 chalk 5.2.0 版本的 AI 聊天机器人那里复制了一段代码,导致文件中出现了类似的导入:

import chalk from "npm:chalk@5.2.0";

幸运的是,您的 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:chalk@5.3.0": "npm:chalk@5.3.0"
 6 | -    },
 7 | -    "npm": {
 5 | +      "npm:chalk@5.2.0": "npm:chalk@5.2.0",
 6 | +      "npm:chalk@5.3.0": "npm:chalk@5.3.0"
 7 | +    },
 8 | +    "npm": {
 9 | +      "chalk@5.2.0": {
10 | +        "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
11 | +        "dependencies": {}
12 | +      },

如果您打算明确更新锁文件,可以指定 `--frozen=false`,这将更新锁文件而不会出错。

有了上述设置,每次依赖更新都需要使用 `--frozen=false` 标志运行命令或任务,从而使这些更新变得有意和明确。

最后,`--lock-write` 现已废弃,并将在 Deno 2 中移除。您可以用 `--frozen=false` 替换 `--lock-write` 的用法。

`deno install` 更新

在 Deno 2 中,`deno install` 子命令的行为将更像 `npm install`,以支持常见的工作流程。目前在 Deno 中,`deno install ` 会全局安装一个二进制包。在 Deno 2 中,`deno install ` 默认会**本地安装**一个包,为项目添加新的依赖项(类似于 `deno add `)并进行缓存。此外,不带参数的 `deno install` 将缓存 `package.json` 或导入映射中列出的本地依赖项,并在适用情况下设置本地 `node_modules` 目录。要全局安装,您需要指定 `--global`(`-g`)标志:`deno install --global `。

要在您的项目中试用新的安装命令,请使用 `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` 期间)执行。

一些包依赖其安装脚本来执行设置步骤(例如,下载或构建原生插件的artifact),如果不安执行,它们将无法正常工作。以前,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` 子命令的缺点和较差的开发者体验(DX)。考虑到这一点,`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 File 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 notebooks 改进

您现在可以在 Jupyter notebook 中使用 `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()` 调用将返回编译过程中指定的值,而不是用户系统上的当前变量。

$ 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` 文件。其中的配置将应用于每个打开的源文件。这使得某些单体仓库配置无法实现。

1.45 版本使语言服务器更能独立于编辑器中打开的根文件夹。现在可以检测到子目录中的配置文件,即使存在多个。每个被发现的 `deno.json` 或 `deno.jsonc` 都将生成一个独立的作用域,拥有自己的类型检查环境、模块解析等。您可以为 `compilerOptions.libs` 配置不同的条目,或导入对全局类型进行增强的模块,这些都不会污染其他 `deno.json[c]` 作用域的环境。

标准库更接近稳定版

Deno 标准库提供了一组高质量的包,这些包经过核心团队审计,并保证与 Deno 兼容。

正如我们之前的博客文章中所述,标准库目前正在进行稳定化工作,目标是将 38 个包中的 31 个稳定下来。

截至目前,我们已稳定 13 个包

  1. @std/assert
  2. @std/bytes
  3. @std/collections
  4. @std/crypto
  5. @std/data-structures
  6. @std/encoding
  7. @std/html
  8. @std/media-types
  9. @std/msgpack
  10. @std/path
  11. @std/regexp
  12. @std/toml
  13. @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 进行开发!