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

Deno 1.42:使用 JSR 改进依赖管理

我们对 Deno 的愿景是简化编程,其中一个重要方面就是管理依赖项。尽管 npm 已成为最成功的开源注册表,但在其上使用和发布模块已变得越来越复杂

基于 npm 的成功,JSR 提供了一个现代的、TypeScript 优先的、跨平台兼容的注册表,并已完全集成到 Deno 中。

Deno v1.42 通过deno publishdeno add 子命令提供了更强大的依赖管理功能,它们可以从 JSR 和 npm 发布和安装模块。此外,此版本还提供了改进的 Node/npm 兼容性多项 LSP 改进更快的启动时间(以及其他性能优势)等功能。

如果您已安装 Deno,请在您的终端中升级到 1.42 版本:

deno upgrade

如果您尚未安装 Deno,可以使用以下命令之一安装,或通过许多其他方式安装。

MacOS / Linux 安装

curl -fsSL https://deno.land/install.sh | sh

Windows 安装

irm https://deno.land/install.ps1 | iex

以下是 Deno 1.42 的新功能概览:

JSR、deno publishdeno add

JSR 是一个适用于现代 JavaScript 和 TypeScript 包的全新开源注册表。阅读我们构建 JSR 的原因。JSR 使用起来非常愉快。它消除了分发 TypeScript 和 JavaScript 的所有麻烦。我们相信您一定会喜欢它。

在 1.42 版本中,Deno 增加了对 JSR 的一流支持。这意味着无需任何额外工具,您就可以使用和发布模块到 JSR。

有两个新的子命令。首先是 deno add。它的工作方式与 npm add 类似,但默认用于 JSR 包。例如,如果您想从 JSR 使用 @std/assert,只需运行:

deno add @std/assert

这将添加一个导入映射条目,让您可以在代码中轻松导入:

import { assertEquals } from "@std/assert";
assertEquals(1, 2);

请注意,deno add 也支持使用 npm: 前缀添加 npm 包。

对于模块作者来说,deno publish 正如您所期望的,它会发布到 JSR。您可以在此处阅读所有相关内容。

JSR 也完全集成到 Deno 的 LSP 和 VS Code 扩展中。即使使用 TypeScript,go-to-definition 也能正常工作。JSR 包的智能感知功能应该也能完美运行。

我们非常乐意听取您对这些新功能的反馈

Node.js 和 npm 兼容性

此版本在使 Deno 与 Node.js 兼容方面进行了大量改进:

  • async_hooks 模块现在支持 EventEmitterAsyncResource AsyncLocalStorage.enterWith() API #22994 #22740

  • child_process.spawn()stdio 配置中正确处理 null #23048

  • crypto 模块正稳步完善。在此版本中,我们添加了 getRandomValues()subtlegetCipherInfo()publicKey()createPublicKey() API,并在多个 API 中添加了对更多曲线的支持。这些更改应能解除 ssh2web-pushoctokit 等流行包的使用限制。#22882 #22891 #23028

  • fs 获得了对 Windows “junctions”FsWatcher.ref()FsWatcher.unref()fs.statfs() API 的支持。#22987 #22294

  • http 模块现在导出 validateHeaderName()validateHeaderValue() API,并且 ServerResponse 现在正确支持设置 HTTP 方法。#22630 #22616

  • http2 获得了对 createServer() API 的基本支持。#22708

  • 现在支持 module.isBuiltin() #22817

  • process.arch 现在支持 "riscv64"

  • process.argv0 现在已正确设置

  • process.version 已更新为返回 Node.js 的最新 LTS 版本 v20.11.1

  • process.setSourceMapsEnabled 现已可用,但为无操作(no-op)

  • punycode 模块工作正常 #22847

  • string_decoder.StringDecoder() 与 Node.js 行为一致 #22933

  • timers.setImmediate 与 Node.js API 和行为一致 #22808

  • 现在支持 util.styleText #22758

  • worker_threads 模块经过重大改造。它现在正确支持 ES 模块和 CommonJS。以下 API 现已支持:parentPortworkerDataisMainThreadthreadIdreceiveMessageOnPort()ref()unref()。Worker 现在同步设置,并在空闲时自动终止。#22841 #20794 #22950 #22647 #22884 #22815 #22766 #22778

  • v8.serialize()v8.deserialize() 已实现 #22975 #22975

以及与 npm 兼容性相关的几项改进:

  • 用户代码现在可以从 node_modules/ 目录正确导入 CommonJS 文件

  • 现在支持内部条件导出(以 # 开头的导出,例如 #crypto

  • 在类型检查期间,CSS 文件可以从 npm 包中正确解析

此外,设置 node_modules/ 目录的性能也得到了改进——在 Deno v1.42 中,您可以看到高达 1.7 倍的速度提升。

deno task

deno task 中已支持所有以 #!/usr/bin/env -S 开头的 shebang 的跨平台功能。

给定一个 script.ts 文件和 deno.json

#!/usr/bin/env -S deno run
console.log("Hello there!");
{
  "tasks": {
    "hi": "./script.ts"
  }
}

现在,即使在 Windows 机器上,运行此任务也有效:

> pwd
C:\Users\david\dev\my_project
> deno task hi
Hello there!

退出状态变量

shell 现在支持使用 $? 获取上次运行命令的退出代码。

{
  "tasks": {
    // outputs 10
    "output": "deno eval 'Deno.exit(10)' || echo $?"
  }
}

改进的重定向支持

现在已实现输入重定向和更多文件描述符重定向。

{
  "tasks": {
    // redirect file.txt to the stdin of gzip
    "input-redirect": "gzip < file.txt",
    // redirect stdout to stderr
    "stdout-err": "deno run main.ts >&2",
    // redirect stderr to stdout
    "stderr-out": "deno run main.ts 2>&1"
  }
}

任务描述

如果您使用 JSONC 文件,现在可以通过注释为任务添加描述。

{
  "tasks": {
    // Start development server
    "dev": "deno run --watch main.ts",

    /**
     * Run tests with coverage and output HTML report
     */
    "coverage": "deno test --coverage **/*_test.ts && deno coverage --html"
  }
}
$ deno task
- dev
  // Start development server
  deno run --watch main.ts

- coverage
  // Run tests with coverage and output HTML report
  deno test --coverage **/*_test.ts && deno coverage --html

deno lint --fix

已实现基础设施,可以在命令行上通过快速修复自动修复 lint 规则,并在编辑器中进行操作。

例如,给定以下代码:

window.onload = () => console.log("Hi there!");

deno lint 现在输出如下:

> deno lint
error[no-window]: window is deprecated and scheduled for removal in Deno 2.0
 --> main.ts:1:1
  |
1 | window.onload = () => console.log("Hi there!");
  | ^^^^^^
  = hint: Instead, use `globalThis`

  docs: https://lint.deno.land/rules/no-window


Found 1 problem (1 fixable via --fix)
Checked 1 file

请注意文本 (1 fixable via --fix)。让我们试试看:

> deno lint --fix
Checked 1 file
> cat main.ts
globalThis.onload = () => console.log("Hi there!");
> deno lint
Checked 1 file

目前,这仅适用于三个 lint 规则,但列表将随着时间增长。

--watch-exclude=...

有时在使用 --watch 标志时,您可能不希望某些文件触发重启。现在可以通过 --watch-exclude 标志实现此功能。

# exclude file1.ts and file2.ts from being watched
deno run --watch --watch-exclude=file1.ts,file2.ts main.ts

您也可以排除模式,但请记住用引号括起来,以防止您的 shell 在将参数发送到 Deno 之前展开它们。

# exclude any .js file from being watched
deno run --watch --watch-exclude='*.js' main.ts

jsr 标签和 verbatim-module-syntax lint 规则

包含 nameversionexports 字段的 deno.json 文件现在会自动选择加入 jsr lint 规则标签。

此标签包含以下规则:

  • no-slow-types
  • verbatim-module-syntax (可通过 --fix 修复)

no-slow-types lint 规则是 JSR 特有的,您可以在 jsr.io 上阅读相关内容。verbatim-module-syntax lint 规则强制要求 importexport 声明仅在其在类型位置使用时才将其标识符定义为仅类型。这对于确保发布在 jsr.io 上的代码在更多场景中工作至关重要。您可以在 TypeScript 5.0 发布说明中阅读有关逐字模块语法的信息。

应用程序执行过程中不再进行类型检查

以前,如果您使用 --check 标志运行 deno run,Deno 可能会在遇到静态无法分析的动态导入或启动 worker 时,在执行过程中进行类型检查。

此功能带来了很大的维护负担,对 JSR 提出了一些挑战,并可能导致正在运行的应用程序在执行过程中失败的不良行为。因此,初始类型检查之后不再进行类型检查(强调:deno run --check main.ts 仍然在执行任何模块之前进行类型检查)。

如果需要,建议您改用 deno check 子命令来对这些模块进行类型检查。

即将到来的 deno install 更改

deno install 允许您轻松安装和分发可执行代码。

$ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
✅ Successfully installed file_server.
$ file_server
Listening on http://127.0.0.1:4507

我们收到了反馈,虽然此命令很有用,但许多用户期望它能将依赖项“安装”到项目本地——就像之前引入的 deno add 一样。

为了更好地符合预期,deno install 在 Deno 2 中将更改为将脚本安装到项目本地。也就是说,deno install 将成为 deno add 的别名。

当前行为仍将通过 -g / --global 标志支持,以告知 Deno 您希望全局安装脚本。

$ deno install --global --allow-net --allow-read https://deno.land/std/http/file_server.ts
✅ Successfully installed file_server.

如果您省略 -g / --global 标志,Deno 现在将警告您并建议使用它。

语言服务器改进

v1.37 以来,我们的 LSP 已支持 npm: 规范符的补全。在 v1.42 中,我们不仅增加了对 jsr: 规范符的支持,还支持包名和版本的补全。

import "jsr:@std/a";
//     "jsr:@std/archive";
//     "jsr:@std/assert"; ✔️
//     "jsr:@std/async";
//     "jsr:@std/data-structures";
//     "jsr:@std/datetime";
//     ...
import "jsr:@std/assert@";
//     "jsr:@std/assert@0.220.1"; ✔️
//     "jsr:@std/assert@0.219.1";
//     "jsr:@std/assert@0.219.0";
//     "jsr:@std/assert@0.218.2";
//     "jsr:@std/assert@0.218.1";
//     ...

其他改进和修复:

  • 在 JSR 导入悬停文本中包含注册表 URL。
  • 不警告从 .js 到 .d.ts 文件的本地文件“重定向”。
  • 不将符号重命名应用于供应商远程模块。
  • 对包规范符导入映射键应用尾随斜杠扩展。

性能

此版本整体性能得到了多项改进,其中最显著的是:

更快的启动时间: Linux 上的启动时间提高了 10%。引导初始化现在在快照时预热,并减少了内存分配。

更高效的 setTimeoutsetInterval 定时器经过了重大重写。创建一百万个定时器大约需要 1.4 秒,而 Deno 1.41 中需要 5.9 秒,内存使用量也减少了高达 70%。我们还有一些优化工作将在未来几个月内进行。

V8 12.3 和 TypeScript 5.4.3

Deno 1.42 附带了 V8 12.3 和 TypeScript 5.4.3。值得注意的更改包括支持 Set 方法支持 Iterator Helpers

以下现在可用:

DENO_FUTURE=1 环境变量

Deno v1.42 添加了一个新的环境变量 DENO_FUTURE=1,它将启用期待已久、多次延迟的 Deno 2 中的更改。

目前 DENO_FUTURE=1 启用以下更改:

  • 移除 window 全局对象
  • 移除以下 Deno API:Deno.BufferDeno.closeDeno.copyDeno.FileDeno.FsFile.prototype.ridDeno.fstatDeno.fstatSyncDeno.ftruncateDeno.ftruncateSyncDeno.flockDeno.flockSyncDeno.funlockDeno.funlockSyncDeno.iterDeno.iterSyncDeno.metricsDeno.readAllDeno.readAllSyncDeno.readDeno.readSyncDeno.resourcesDeno.seekDeno.seekSyncDeno.shutdownDeno.writeAllDeno.writeAllSyncDeno.writeDeno.writeSync

在后续版本中,我们将添加更多 Deno 2 中将发生的更改,包括对 node_modules/ 目录处理方式的更改。特别是在 DENO_FUTURE 下启用 BYONM

如果您想为即将发布的主要 Deno 2 版本做好代码的未来兼容性准备,您可以在 shell 或 CI 环境中设置 DENO_FUTURE=1 环境变量。

感谢我们的贡献者!

没有我们社区的帮助,我们就无法构建 Deno!无论是通过在我们的社区 Discord 服务器中回答问题,还是报告错误,我们都非常感谢您的支持。特别是,我们要感谢以下对 Deno 1.42 做出贡献的人:Dimitris Apostolou、Don Jayamanne、Eric Long、Kenta Moriuchi、Nano Miratus、Sol Boucher、Viktor Marinho、cui fliter、guangwu、mash-graz、mimikun、tuhana、ud2 和 Łukasz Czerniawski。

您想加入 Deno 贡献者的行列吗?请查看我们的贡献文档,下次再见到您出现在贡献者名单上。

信不信由你,上面列出的更改仍然没有告诉您 1.42 中所有改进的地方。您可以在 GitHub 上查看 Deno 1.42 中合并的完整拉取请求列表

感谢您关注我们的 1.42 版本,我们希望您喜欢使用 Deno 进行构建!

🍋 Fresh 2.0 即将到来。

我们的下一个主要 Fresh 版本将更简单,具有更具组合性、类似 Express 的 API。在此处阅读更多信息