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 兼容性改进
此版本包含多项 npm 兼容性改进和自 1.28.0 以来的 30 多个错误修复。
通过环境变量自定义注册表支持
Deno 现在遵循 NPM_CONFIG_REGISTRY
环境变量,该变量允许指定自定义 npm 注册表。
# change this to a custom registry
> NPM_CONFIG_REGISTRY=https://registry.npmjs.org deno run main.ts
在未来的版本中,将支持为每个包作用域使用不同的注册表,并支持设置凭据。请关注 issue #16105 以获取更新。
deno install
支持
npm 说明符现在可以与 deno install
一起使用。
> deno install -A npm:cowsay@1.5.0
✅ 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 |
|| ||
这将额外为命令在首次运行时创建 lockfile,以确保后续每次运行都使用相同的 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
默认以无权限运行
在此版本之前,deno
和 deno 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
标志现在生效
如果您将 REPL 与 --eval
或 --eval-file
一起使用以构建自定义 REPL,则可能不希望在启动时看到默认横幅打印出来。REPL 现在遵循 --quiet
标志,该标志将隐藏 REPL 的任何辅助输出
$ deno --quiet
>
生活质量改进
deno init
改进
deno init
子命令在 v1.25 版本中添加,允许用户快速搭建新项目(尽管它是完全可选的)。虽然此子命令非常方便,但它也非常简洁 - 仅生成 main.ts
和 main_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
以及 lockfile 指定文件包含和排除项。
配置 deno bench
{
"bench": {
"files": {
"include": ["./benches/"],
"exclude": ["./benches/testdata/"]
}
}
}
如果您想为 lockfile 使用非默认文件名,您可以这样做…
{
"lock": "./lock.file"
}
…或者您可以完全禁用 lockfile 的使用
{
"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,它允许您使用 await
关键字,而无需将代码包装在 async IIFE 中。这非常有用且符合人体工程学,但在某些情况下,等待的 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 run
和 deno check
命令之间存在差异,其中 deno run
的类型检查所有代码需要执行 deno run --check=all main.ts
,但使用 deno check
执行相同的操作需要使用 --remote
标志—deno check --remote main.ts
。
现在已通过将 deno check
中的 --remote
重命名为 --all
解决了此问题,--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();
createNew
选项用于 Deno.writeFile
和 Deno.writeTextFile
此版本为 Deno.writeFile
、Deno.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
模块。它是一个用于检查复杂类型行为的测试实用程序。该模块的灵感来自 Conditional Type Checks 并从 David Sherret 移植而来。
import {
assertType,
IsExact,
IsNullable,
} from "https://deno.land/std@0.167.0/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 在某些地方在单个文件中实现。此类模块的示例包括 bytes
、datetime
、io
等。另一方面,某些模块具有每个导出的项都在单个文件中实现的模式(我们在此处将此模式称为单导出模式)。此类模块的示例包括 collections
、fs
等。到目前为止,对于使用哪种模式来组织模块还没有明确的策略,但我们决定在适当的情况下转向后者(单导出)模式。
在此版本中,以下 4 个模块 archive
、bytes
、io
和 stream
被重组为单导出模式。因此,以下路径已弃用,将在以后的版本中删除(有关删除的确切版本,请参阅 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.ts
(Untar
导出已弃用。)
您可以在 主页的搜索对话框中找到更新后的路径。
感谢 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 建议并贡献了这些更改。
如果您有兴趣帮助在未来的版本中发布某些内容,请查看我们的招聘信息。