跳至主要内容
Deno 2 终于来了 🎉️
了解更多
Deno 1.29 Custom npm registry support

Deno 1.29:自定义 npm 注册表支持

Deno 1.29 已标记并发布,包含以下新功能和更改

如果您已经安装了 Deno,则可以通过运行以下命令将其升级到 1.29

deno upgrade

如果您是第一次安装 Deno

# MacOS and Linux
curl -fsSL https://deno.land/x/install/install.sh | sh

# Windows
iwr https://deno.land/x/install/install.ps1 -useb | iex

点击此处 获取更多安装选项。

npm 兼容性改进

此版本包含自 1.28.0 以来的一些 npm 兼容性改进和 30 多个错误修复。

通过环境变量支持自定义注册表

Deno 现在支持 NPM_CONFIG_REGISTRY 环境变量,该变量允许指定自定义 npm 注册表。

# change this to a custom registry
> NPM_CONFIG_REGISTRY=https://registry.npmjs.org deno run main.ts

在将来的版本中,将支持为每个包范围使用不同的注册表,以及设置凭据的功能。请关注问题 #16105 以获取更新。

deno install 支持

npm 说明符现在可以与 deno install 一起使用。

> deno install -A npm:[email protected]
✅ Successfully installed cowsay
C:\Users\david\.deno\bin\cowsay.cmd
C:\Users\david\.deno\bin\cowsay (shell)
> cowsay Hello from deno!
 __________________
< Hello from deno! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

这将在第一次运行时为命令额外创建一个锁定文件,以确保每次后续运行都使用相同的 npm 依赖项版本。

REPL 更改

REPL 是开发人员工具链中非常有价值的工具;允许快速实验。此版本为 REPL 带来了大量更新

npm 支持

您现在可以直接从 REPL 使用 npm 包。至于其他 Deno 子命令,无需事先安装步骤 - 只需导入包,就可以开始使用。

$ deno
> import cowsay from "npm:cowsay"
undefined
> console.log(cowsay.say({ text: "hello world" }))
 _____________
< hello world >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
undefined
>

deno repl 默认情况下不带权限运行

在此版本之前,denodeno repl 命令都以授予所有权限的方式启动 REPL。虽然对于快速实验来说,不必回答权限提示很有用,但这与 Deno 的“默认安全”理念有些冲突。

此版本将 deno repl 子命令更改为默认情况下不授予任何权限。可以使用 --allow-* 标志指定权限,或者在调用需要权限的 API 时,您可以选择推迟到权限提示

$ deno repl --allow-write
Deno 1.29.0
Run repl.help() to see help
exit using ctrl+d, ctrl+c, or close()
> Deno.writeTextFileSync("hello.txt", "hello world");
undefined
$ deno repl
Deno 1.29.0
Run repl.help() to see help
exit using ctrl+d, ctrl+c, or close()
> Deno.writeTextFileSync("hello.txt", "hello world");
⚠️  ┌ Deno requests write access to "hello.txt".
   ├ Requested by `Deno.writeFileSync()` API
   ├ Run again with --allow-write to bypass this prompt.
   └ Allow? [y/n] (y = yes, allow; n = no, deny) > y
✅ Granted write access to "hello.txt".
undefined

为了更加明确,运行 deno 将显示一个横幅,告知所有权限都已允许,并建议如果您想限制权限,可以使用 deno repl 子命令

$ deno
Deno 1.29.0
Run repl.help() to see help
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed.
To specify permissions, run `deno repl` with allow flags.
>

更可靠的历史记录处理

REPL 现在将在每个执行的语句上更新历史记录文件,使历史记录不那么零碎。

--quiet 标志现在已得到尊重

如果您使用 --eval--eval-file 与 REPL 构建自定义 REPL,您可能不希望在启动时看到默认横幅打印。REPL 现在尊重 --quiet 标志,该标志将隐藏 REPL 的任何辅助输出

$ deno --quiet
>

生活质量改进

deno init 改进

deno init 子命令是在 v1.25 版本 中添加的,允许用户快速搭建新的项目(虽然这完全是可选的)。虽然此子命令非常方便,但它也很简陋 - 只能生成 main.tsmain_test.ts 文件。

为了使它更实用,并允许 IDE 发现我们刚刚初始化了一个新的 Deno 项目,deno init 还将生成一个 deno.jsonc 文件以及一个 main_bench.ts 文件。

子命令的输出也进行了刷新。

Deno v1.28 中的 deno init

$ deno init ./my_deno_project
✅ Project initialized
Run these commands to get started
  cd ./my_deno_project
  deno run main.ts
  deno test

Deno v1.29 中的 deno init

$ deno init ./my_deno_project
✅ Project initialized

Run these commands to get started

  cd ./my_deno_project

  // Run the program
  deno run main.ts

  // Run the program and watch for file changes
  deno task dev

  // Run the tests
  deno test

  // Run the benchmarks
  deno bench

感谢 sigmaSd 为此改进做出贡献。

配置文件改进

从此版本开始,您可以为 deno bench 指定文件包含和排除项,以及配置文件中的锁定文件。

配置 deno bench

{
  "bench": {
    "files": {
      "include": ["./benches/"],
      "exclude": ["./benches/testdata/"]
    }
  }
}

如果您想对锁定文件使用非默认文件名,您可以这样做…

{
  "lock": "./lock.file"
}

…或者您可以完全禁用使用锁定文件

{
  "lock": false
}

您的 IDE 应该能够自动建议这些新选项。

感谢 Geert-Jan Zwiers@roj1512 为此改进做出贡献。

--allow-* 标志使用不正确时发出警告

Deno 允许您通过提供各种 --allow-* 标志来选择加入沙箱。在执行 deno run 时,这些标志需要放在脚本名称之前,否则它们将作为 Deno.args 传递给脚本本身。

// example.js
console.log("cli args", Deno.args);
await Deno.writeTextFile("./hello.txt", "hello world");

在 Deno v1.29 之前,您将获得以下输出

$ deno run example.js --allow-write
cli args [ "--allow-write" ]
⚠️  ┌ Deno requests write access to "./hello.txt".
   ├ Requested by `Deno.writeFile()` API
   ├ Run again with --allow-write to bypass this prompt.
   └ Allow? [y/n] (y = yes, allow; n = no, deny) >

我们发现,将权限标志放在脚本名称之后是一个常见的错误,因此从本版本开始,Deno 将会警告你,这可能是无意的,并建议如何正确运行程序。

$ deno run example.js --allow-write
Permission flags have likely been incorrectly set after the script argument.
To grant permissions, set them before the script argument. For example:
    deno run --allow-read=. main.js
cli args [ "--allow-write" ]
⚠️  ┌ Deno requests write access to "./hello.txt".
   ├ Requested by `Deno.writeFile()` API
   ├ Run again with --allow-write to bypass this prompt.
   └ Allow? [y/n] (y = yes, allow; n = no, deny) >

感谢 Asher Gomez 为此改进做出贡献。

在顶级 await 中显示未解决的 Promise

Deno 支持 顶级 await,它允许你在不将代码包装在异步 IIFE 中的情况下使用 await 关键字。这非常有用且符合人体工程学,但在某些情况下,等待的 Promise 永远不会解决 - 大多数情况下,是由于代码中的错误。

// example.js
await new Promise((resolve) => {}); // this promise will never resolve!
console.log("hello world");

在这种情况下,会返回错误并终止程序执行。

deno run example.js
error: Module evaluation is still pending but there are no pending ops or dynamic imports. This situation is often caused by unresolved promises.

虽然错误提示了可能存在的问题,但用户需要通读代码并尝试找出问题所在。得益于新的 v8 API,现在会显示更友好的错误以及未解决的 Promise 的堆栈跟踪。

$ deno run example.js
error: Top-level await promise never resolved
await new Promise((_resolve) => {});
^
    at <anonymous> (file:///Users/ib/dev/deno/example.js:1:1)

默认情况下忽略 node_modules.git 文件夹

从本版本开始,所有内置的 Deno 工具默认情况下都会跳过 node_modules/.git/ 目录。你可以运行格式化程序(deno fmt)或 linter(deno lint)之类的工具,而不必担心它们会开始遍历这些大型目录。你仍然可以通过显式指定这些目录来选择搜索它们(例如,deno fmt node_modules/)。

deno check --remote 标志重命名为 --all

deno rundeno check 命令之间存在差异,其中为 deno run 检查所有代码需要执行 deno run --check=all main.ts,而使用 deno check 执行相同的操作则需要使用 --remote 标志 - deno check --remote main.ts

现在,deno check 中的 --remote 已重命名为 --all,其中还包括 npm 包。之前的命令仍然可以使用,但建议使用新的命令。

新的 --inspect-wait CLI 标志

Deno 能够连接到调试器,例如 Chrome DevTools、VSCode 等。如果指定 --inspect--inspect-brk 标志,就可以实现此目的。前者将启用调试器并立即运行你的代码,而后者将启用调试器,等待其连接并在你的代码的第一行停止执行。

我们收到了报告,表明在某些情况下,等待调试器连接但不必在用户代码的第一行断点很有用。我们很高兴地宣布我们添加了一个新的 --inspect-wait 标志,它满足了这一需求 - 它将在运行用户代码之前等待调试器会话建立,但不会在代码的第一行设置断点。

类似于 --inspect--inspect-brk--inspect-wait 标志允许你提供一个可选的值,其中包含调试器连接到的网络地址,如下所示:--inspect-wait=127.0.0.1:3000

内联提示在 VSCode 扩展中默认启用

我们 在 Deno v1.27 中添加了对内联提示的支持。它们默认情况下是禁用的,因为我们想要确保一切正常。现在我们确信此功能按预期工作,并且很高兴地宣布,Deno 的 VSCode 扩展 的最新版本现在默认情况下使用内联提示(遵循默认的 VSCode 设置)。

如果你想禁用它们,可以在你的 VSCode 用户设置 中设置以下设置。

{
  "deno.inlayHints.parameterNames.enabled": "none",
  "deno.inlayHints.parameterTypes.enabled": false,
  "deno.inlayHints.variableTypes.enabled": false,
  "deno.inlayHints.propertyDeclarationTypes.enabled": false,
  "deno.inlayHints.functionLikeReturnTypes.enabled": false,
  "deno.inlayHints.enumMemberValues.enabled": false
}

或者,你也可以在 VSCode 中禁用所有内联提示,方法是设置。

{
  "editor.inlayHints.enabled": "off"
}

Deno API 的更改

稳定性

以下 API 在本版本中已稳定,不再需要使用 --unstable 标志。

  • Deno.TcpConn.setNoDelay()
  • Deno.TcpConn.setKeepAlive()

删除不稳定的 Deno.spawn

本版本中的重大更改是删除了不稳定的 Deno.spawn()Deno.spawnSync()Deno.spawnChild() API。所有这些 API 都已被统一的 Deno.Command API 替换。子进程 API 很难设计,使其既能满足常见任务的符合人体工程学要求,又能满足你在需要对正在生成的子进程进行低级控制时的灵活性。

让我们看看如何迁移代码的示例。

const { stdout, stderr } = await Deno.spawn("echo", { args: ["foo"] });

// becomes...

const { stdout, stderr } = await new Deno.Command("echo", { args: ["foo"] })
  .output();
const { stdout, stderr } = Deno.spawnSync("echo", { args: ["foo"] });

// becomes...

const { stdout, stderr } = new Deno.Command("echo", { args: ["foo"] })
  .outputSync();
const child = Deno.spawnChild("cat", { stdin: "piped" });

// becomes...

const child = new Deno.Command("cat", { stdin: "piped" }).spawn();

Deno.Command#.spawn() 在 stdout 和 stderr 中默认情况下为 “继承”

调用 .spawn() 时,不稳定的 Deno.Command 在 stdout 和 stderr 中默认情况下为 “继承”。调用 .output().outputSync() 时,它默认情况下仍然为 “管道”。

// outputs "1\n" to stdout and "2\n" to stderr
new Deno.Command("deno", {
  args: ["eval", "console.log(1); console.error(2);"],
}).spawn();

Deno.writeFileDeno.writeTextFilecreateNew 选项

本版本在 Deno.writeFileDeno.writeTextFile 以及相应的同步 API 中添加了一个 createNew 选项。

// ok
await Deno.writeTextFile("file.txt", "some text", { createNew: true });
// error: Deno.errors.AlreadyExists
await Deno.writeTextFile("file.txt", "some text", { createNew: true });

以前,你需要使用 Deno.open API 来获得此功能,这过于冗长。

TypeScript 4.9

Deno v1.29 附带最新稳定版本的 TypeScript。有关 TypeScript 中新功能的更多信息,请参阅 TypeScript 的 4.9 博客文章

对标准模块的更改

添加 testing/types 模块

在本版本中,添加了 testing/types 模块。这是一个用于检查复杂类型行为的测试工具。该模块的灵感来自于 条件类型检查(由 David Sherret 编写),并从该项目移植而来。

import {
  assertType,
  IsExact,
  IsNullable,
} from "https://deno.land/[email protected]/testing/types.ts";

const result = "some result" as string | number;

// compile error if the type of `result` is not exactly `string | number`
assertType<IsExact<typeof result, string | number>>(true);

// causes a compile error that `true` is not assignable to `false`
assertType<IsNullable<string>>(true); // error: string is not nullable

感谢 Lino Le Van 为此功能做出贡献。

向单一导出模式的结构变化

在标准模块中,某些地方在单个文件中实现了多个 API。例如 bytesdatetimeio 等模块。另一方面,有些模块遵循一种模式,即每个导出项都在单个文件中实现(我们将这种模式称为单一导出模式)。例如 collectionsfs 等模块。目前尚未明确规定模块组织应使用哪种模式,但我们决定在适当的情况下迁移到后一种(单一导出)模式。

在本版本中,以下 4 个模块 archivebytesiostream 重构为单一导出模式。因此,以下路径已弃用,并将 在以后的版本中删除(有关删除的具体版本,请参阅 IDE 中的弃用消息)。如果您从这些路径导入,请更新您的导入路径。

  • std/streams/buffer.ts
  • std/streams/conversion.ts
  • std/streams/delimiter.ts
  • std/io/buffer.ts(除 Buffer 类以外)
  • std/io/files.ts
  • std/io/readers.ts
  • std/io/util.ts
  • std/io/writers.ts
  • std/archive/tar.tsUntar 导出已弃用。)

您可以在 主页 的搜索对话框中找到更新后的路径。

感谢 Asher Gomez 为此更改提供建议和贡献。

API 重命名

在本版本中,以下 API 已重命名。如果您在代码中直接使用这些 API,请进行更新。

  • std/dotenv/mod.ts
    • config -> load
    • configSync -> loadSync
    • 注意:参数也已重命名。有关详细信息,请参阅 类型定义
  • std/fmt/bytes.ts
    • prettyBytes -> format
  • std/fmt/duration.ts
    • prettyDuration -> format

感谢 Tim Reichen 为此更改提供建议和贡献。




如果您想帮助发布未来版本的内容,请查看 我们的招聘信息