Deno 1.37:Jupyter Notebooks 中的现代 JavaScript
Deno 的使命是大幅简化软件开发。在 Deno 1.37 中,我们很高兴能将此扩展到交互式 Jupyter Notebook。从 1.37 开始,您可以使用新的 deno jupyter
命令来创建可用于 Notebook 的 Deno 内核。此外,Deno 1.37 还附带了更强大的 Visual Studio Code 和 LSP 支持、更好的测试性能、改进的 Node 兼容性以及许多错误修复。
如果您已经安装了 Deno,请在终端中通过以下命令升级到 1.37 版本
deno upgrade
如果您尚未安装 Deno,可以使用以下命令之一安装,或通过许多其他方式安装。
MacOS / Linux 安装
curl -fsSL https://deno.land/x/install/install.sh | sh
Windows 安装
irm https://deno.land/install.ps1 | iex
以下是 Deno 1.37 新功能的概述。
Deno 1.37 概览
- 📒 Jupyter Notebook Deno 现在与 Jupyter Notebook 无缝集成,弥合了脚本编写和分析之间的差距。
- 🖥️ VSCode 扩展和语言服务器 VSCode 扩展持续改进,包括更好地检测 `deno.json`、引入 `deno.disablePaths` 配置、更好地支持文件重命名、npm 说明符补全、一个名为 `deno.suggest.completeFunctionCalls` 的新配置以及更多修复。
- 🧪 测试改进 更简单、更快、更好!我们改进了测试套件,使其更直观地编写测试,并确保更快的反馈循环。
- ⬢ Node.js 兼容性改进 内置 Node API 的持续改进意味着 Deno 现在支持 `npm:mssql`、`npm:mineflayer` 和 `npm:web-push` 等模块。大多数 NPM 模块在 Deno 中都可以开箱即用。
- 🏝️ 体验优化 支持新的导入属性语法,使用 `Deno.serve()` 优雅关闭,以及大量的性能改进。
Jupyter Notebook 集成
Deno v1.37 内置支持 Jupyter Notebook 内核,这带来了现代 JavaScript 和 TypeScript,并开启了全新的数据科学和机器学习可能性。
如果您尚未安装,请先安装 Jupyter——此命令假定您的系统上已安装 Python 和 pip。
pip install jupyterlab
如果您安装了 Python 3,您可能需要改用 pip3
命令。其他安装选项此处有介绍。
要在 Jupyter 中开始使用 Deno,请运行
deno jupyter --unstable
然后按照提示完成安装。有关 deno jupyter --unstable
的更多文档可在此处找到。
您现在可以使用 Jupyter Lab 或您喜欢的支持这些 Notebook 的 IDE 来创建交互式 REPL 会话。
您可以直接从 Notebook 访问所有 Deno 的 API 和 npm 模块。
您不仅可以在 Jupyter Notebook 中使用现代 JavaScript,还可以从 npm 导入 D3 来可视化您的数据。
此外,您还可以通过返回一个包含 Symbol.for("Jupyter.display")
函数的对象,从您的单元格提供富文本输出。
您甚至可以使用 Deno KV Connect 连接到您托管的 Deno KV,并将实时数据直接拉入 Notebook。
最后,如果您正在使用 Noteable.io,您可以今天就在您的托管 Jupyter Notebook 中使用 Deno。Noteable.io 的首席架构师兼 Jupyter 项目核心维护者 Kyle Kelley 描述了此集成所解锁的可能性:
Deno 新的 Jupyter 内核为能编写 JavaScript 的用户的数据科学工作流带来了巨大的潜力。Deno 现代 JavaScript 运行时和内置 TypeScript 支持的原生访问所带来的可能性让我感到兴奋。JavaScript 开发者可以创建 Notebook 来分析数据、构建模型并创建交互式报告。
在 Jupyter JavaScript 内核中配置 Babel 和 TypeScript 的日子一去不复返了。由于 Deno 支持基于 URL 的 ESM 导入,Deno 内核使得共享可在任何地方运行的 Notebook 变得异常容易。依赖项是声明性的。组织可以利用现有的 Jupyter 部署,并立即获得 Deno 安全运行时沙箱的访问权限,而无需放弃 Jupyter 提供的灵活工作流。
有关使用 Deno 的 Jupyter 集成的更多详细信息,请查看我们的文档。我们正在寻求社区对此功能的反馈,因此请尝试使用并让我们知道您是否发现任何问题或缺少的功能。
VSCode 扩展和语言服务器
deno.json
启用
通过检测 为了方便从事非 Deno TypeScript 项目的用户,Deno 扩展默认是禁用的。以前,您必须在编辑器的工作区设置中指定 "deno.enable": true
才能启用它。现在,只要您的项目根目录包含 deno.json
文件,您就可以将其留空。您仍然可以指定 "deno.enable": false
来覆盖此设置。
"deno.disablePaths"
为帮助解决上述情况,引入了新的 "deno.disablePaths"
设置。这是现有 "deno.enablePaths"
设置的补充。如果您有嵌套的非 Deno 子项目,它将禁用指定路径的 Deno 扩展。
// .vscode/settings.json
{
"deno.disablePaths": ["./node_api/", "./vsc_extension/"]
}
自动更新文件重命名时的导入
这是许多语言中广泛使用的重构功能。Deno 的语言服务器现在提供此功能——重命名 JS/TS 文件后,您将收到提示,可以选择更新项目中指向该文件的导入说明符。
NPM 说明符补全
现在,当您在导入说明符中键入 npm:
URL 时,将显示 NPM 包的自动补全选项。这些选项通过搜索 NPM 注册表获取。
import "npm:prea";
// "npm:preact"; ✔️
// "npm:preact-render-to-string";
// "npm:preact-compat";
// "npm:preact-jsx-chai";
// "npm:preact-css-transition-group";
// ...
但可能更有用的是:如果您键入了 npm:<package_name>@
,您将看到该包最新发布版本的自动补全选项。查找有效版本曾是使用 NPM 说明符的繁琐部分。现在这已为您完成。
import "npm:preact@";
// "npm:preact@11.0.0-experimental.1";
// "npm:preact@11.0.0-experimental.0";
// "npm:preact@10.17.1"; ✔️
// "npm:preact@10.17.0";
// "npm:preact@10.16.0";
// ...
函数调用补全
设置 "deno.suggest.completeFunctionCalls": true
以在选择已知函数签名的自动补全选项时包含括号和参数占位符。这是 "typescript.suggest.completeFunctionCalls"
和 "javascript.suggest.completeFunctionCalls"
的重新实现。
// Type the following:
addEventLi
// and select the autocomplete option for `addEventListener`.
// `"deno.suggest.completeFunctionCalls": false`:
addEventListener
// `"deno.suggest.completeFunctionCalls": true`:
addEventListener(type, listener)
deno.cacheOnSave
引入了一个新的 "deno.cacheOnSave"
设置。启用后,当您保存文件时,扩展将自动缓存新的依赖项。这对于经常向项目添加新依赖项的用户来说非常方便,并且无需从命令面板运行“缓存依赖项”命令。目前此设置默认关闭,但我们计划在未来的版本中默认启用它。
测试资源管理器和代码透镜修复
自 1.36.0 以来,许多测试 API 错误已得到修复。
- 测试资源管理器在执行带步骤的测试时不再冻结。
- 当测试步骤的名称更改时,它们在资源管理器中会正确替换。以前,每键入一个字符就会注册一个新步骤,您必须重置语言服务器才能清理它。
- 在某些情况下,具有相同名称的嵌套测试步骤不会被唯一注册,并在资源管理器中共享相同的条目。现在 ID 分配已修复。
- 通过测试资源管理器运行所有测试不再评估不包含任何测试的模块。
- 测试资源管理器中不再显示没有测试的模块。
- 通过代码透镜运行单个测试时,如果文件中的另一个测试设置了
{ only: true }
,以前不会运行任何测试并记录失败,因为使用了only
选项。现在它按预期运行,并正确忽略其他测试。 - 通过代码透镜运行名为
foo
的测试不再运行文件中名称包含foo
的其他测试(例如foobar
)。感谢 @Leokuma! - 现在,包含在测试资源管理器中并显示“运行测试”代码透镜的文件集根据
deno.json
字段exclude
、test.exclude
和test.include
进行过滤。
其他修复
- 在自动导入补全条目的标签描述中显示源模块。
- 相对和裸说明符的优先级高于远程 URL,用于自动导入补全条目。
- 插入自动导入代码时,会遵守格式偏好设置。
- 不以
.json
结尾的 JSON 模块说明符不再显示关于没有默认导出的错误诊断。这会影响数据 URL 和包含查询字符串或片段的说明符。 - 快速修复操作按
tsc
、deno
、然后是deno-lint
的顺序排序。 - 导入补全现在包括本地 JSON 模块。
- 按整个路径组件匹配
"deno.enablePaths"
条目。以前,文件名为条目字符串前缀的文件会被启用(例如,foo
会同时启用foo.ts
和foobar.ts
)。现在它必须是路径前缀,即条目必须是文件的确切名称或其父目录之一。 - 调试测试时始终使用
--inspect-wait
而不是--inspect-brk
。仍存在使用不太适合的--inspect-brk
的情况。感谢 @jeiea! - 正确处理不支持
workspace/configuration
请求的语言服务器客户端。在某些情况下,这些请求被发送到无法处理它们的客户端。 - 删除已失效的
"deno.testing.enable"
设置。此设置没有任何作用。
测试改进
继上一个版本对 Deno 测试 API 的持续改进之后,本月我们也有一些令人兴奋的更新。
速度提升
我们提高了测试运行的性能,Deno 现在每秒可以运行多达 14,000 个测试。这是通过优化 Deno 测试运行器内置的清理器实现的,将每个测试用例的基线开销从 3ms 降低到不足 0.1ms。
我们有进一步的计划来改进测试性能,您可以期待在下一个版本中获得更快的速度。
TAP
测试报告器
deno test
现在可以以 Test Anything Protocol 格式输出测试结果。您可以通过使用 --reporter=tap
标志启用它。
$ deno test --reporter=tap ./test.ts
TAP version 14
# ./test.ts
ok 1 - test 0
ok 2 - test 1
ok 3 - test 2
ok 4 - test 3
ok 5 - test 4
ok 6 - test 5
ok 7 - test 6
ok 8 - test 7
ok 9 - test 8
ok 10 - test 9
1..10
感谢 Valentin Anger 实现了此功能。
聚焦和忽略测试的简写方法
您现在可以使用简写方法 Deno.test.only
和 Deno.test.ignore
来聚焦和忽略测试,如下所示:
// Only run this test
Deno.test.only(function myTest() {
// ...
});
// Do not run this test
Deno.test.ignore(function myTest() {
// ...
});
这是一个小的改动,但比必须指定像 Deno.test({ only : true }, function myTest() ...
这样的选项包更容易、更快地迭代。
体验优化
除了上面描述的更改之外,我们还有大量其他小更改,使 Deno 中的测试体验更好。
过滤后的套件不显示
如果您使用 --filter <name>
标志只运行一部分测试,测试运行器现在只会在输出中显示过滤后的测试。这使得更容易专注于您关心的测试。
Deno v1.37 之前
Deno v1.37 中
ASCII 转义字符不再破坏测试名称
现在,诸如 \n
、\t
等字符在测试名称中已正确转义,因此如果您确实需要在测试名称中包含它们,报告器输出将不会被破坏。
--trace-ops
显示更多详细信息
如果您的测试中存在 ops 泄漏,--trace-ops
标志可以帮助您找到泄漏的来源。在此版本中,此标志变得更智能,可以在更多情况下显示有用的信息。
only
选项
按名称过滤优先于 如果您的测试套件设置了 only
选项为 true
,但您想运行通过名称过滤的其他测试(使用 --filter <name>
标志),则该测试将正常运行。
JUnit 报告包含更多信息
文件、行和列属性已正确添加到生成的报告中。
从覆盖率报告中排除内部代码
通过从生成的报告中排除内部 Deno 代码,覆盖率现在更快且噪声更小。
如果您有其他想法如何改进 Deno 的测试运行器,请在 Deno 的 Bug 跟踪器中提出问题,让我们知道。
Node.js 兼容性改进
此版本中包含许多重要的 Node.js API 修复:
child_process
不再在环境变量为undefined
或null
时抛出错误。crypto
模块实现了 AES GCM 密码。http
现在正确处理Content-Length
标头,发出"error"
事件,正确销毁请求并清理分配的资源。http2
添加了对ClientHttp2Session
和connect
API 的支持。process.title
不再抛出错误。- 现在支持
repl._builtinLibs
。 tls
现在实现了TLSSocket._start
方法。worker_threads.Worker
现在正确处理process.argv
。zlib
支持dictionary
选项。require
现在使用规范化路径来加载内容。- 已测试并正常工作的其他 npm 模块:
mssql
、mineflayer
、infiscal
和web-push
。
如果您想了解更多关于 Deno 中 Node.js 兼容性的信息,请查看我们的 Node.js 兼容性列表。
体验优化
将供应商作为缓存覆盖 (不稳定)
现在可以通过简单地将以下内容添加到您的 deno.json
中来供应商依赖项:
{
"vendor": true
}
下次您运行或缓存(例如 deno cache mod.ts
)时,Deno 将在 ./vendor
文件夹中填充程序使用的远程 https/http 依赖项。
另外,也可以通过 --vendor
标志进行供应商化。
请注意,Deno 对 ./vendor
文件夹的处理方式有所不同,因为它并非总能将 URL 直接映射到文件系统。
您可能会发现此功能比 deno vendor
子命令更容易使用,因为它管理开销极小且适用于更多场景。因此,从 CLI 中移除 deno vendor
子命令并将其作为独立工具分发可能更有意义(有关更多详细信息,请参阅 issue #20584)。
导入属性
此版本添加了对 导入属性提案 的支持。该提案早期被称为“导入断言”,Deno 自 1.17 版本以来就支持它。
导入属性允许您使用 import
声明导入 JSON 文件
import jsonData from "./data.json" with { type: "json" };
它也适用于动态导入
const jsonData = await import("./data.json", { with: { type: "json" } });
使用 assert
的旧语法仍然受支持,但已弃用。我们将在接下来的几个版本中逐步淘汰它;在接下来的版本中,如果您在自己的代码中使用弃用的 assert
语法,Deno 将打印警告。
Deno.Server.prototype.shutdown()
此版本带来了新的、不稳定的 API:Deno.Server.prototype.shutdown(): Promise<void>
。
// Start a server...
const server = Deno.serve((_req) => new Response("hello world!"));
// ...and close it gracefully after 3 seconds.
setTimeout(async () => {
await server.shutdown();
}, 3000);
在此版本之前,只能通过使用在服务器构建期间传递的 AbortSignal
来“突然”关闭服务器。然而,以这种方式关闭服务器并非总是可取的,在大多数情况下,您希望等待所有进行中的请求完成,然后再关闭服务器。
这个新 API 是不稳定的,因为我们希望在稳定它之前收集社区的反馈;此外,我们希望添加一个 timeout
参数,该参数将控制服务器等待挂起请求完成的时间,然后再强制关闭它们。
性能改进
此版本我们优化了许多 Web API 以及 HTTP 相关 API(Deno API 和内置 Node.js API 中)。以下是完整列表:
Event
和addEventListener
经过了深度优化,使其速度大大提高;Event.timeStamp
现在始终设置为 0Headers
针对迭代和查找场景进行了优化,此外标头名称的验证也得到了优化node:http
获得了标头处理的优化——IncomingMessageForServer.headers
现在使用缓存来避免每次访问都计算标头node:buffer
已从头重写,以在输出字符串时提供更快的结果node:net
收到了套接字读取的优化,这使得npm:ws
包的性能大大提高
所有这些优化在 HTTP 基准测试中提供了高达 10% 的 RPS 提升。
感谢 Marcos Casagrande 实现了许多这些优化。
锁文件 v3
锁文件格式已更新至版本 3。Deno 1.37 将在首次运行时自动将您现有的锁文件迁移到新格式,但在旧版本 Deno 中加载 v3 将会出错。
新格式包含重定向信息,Deno 使用这些信息将 http(s) 重定向锁定到它们在插入锁文件时解析到的目标。
std/url
在此版本中,std/url
模块已添加到 Deno 标准库中。std/url
支持对 URL 进行各种类似路径的操作,这些操作不受 Web 标准 URL 方法或属性 的支持。
目前 std/url
包含以下 5 种方法:
basename
dirname
extname
join
normalize
import {
basename,
dirname,
extname,
join,
normalize,
} from "https://deno.land/std@0.202.0/std/url/mod.ts";
const url = new URL("https://example.com/home/page.html?foo=bar");
basename(url); // => "page.html"
dirname(url); // => new URL("https://example.com/home")
extname(url); // => ".html"
join("https://example.com", "foo", "bar.html"); // => new URL("https://example.com/foo/bar.html")
normalize("https://example.com///about///page.html"); // => new URL("https://example.com/about/page.html")
感谢 Aritra Karak 实现了此模块。
std/ulid
此版本中,std/ulid
已添加到 Deno 标准库中。std/ulid
支持生成 ULID
并从给定的 ULID 解码时间戳。
import { decodeTime, ulid } from "https://deno.land/std@0.202.0/ulid/mod.ts";
const id = ulid(); // => "01HARJZ15RFMBVZ1GQ8J4VB6C4"
const timestamp = decode(id); // => 1695189796023
ULID 是 UUID 的替代方案,由于 ULID 的前导部分是从时间戳生成的,因此这些 ID 按生成时间顺序进行词法排序。当您将其用于 Deno KV 项的部分键时,此属性非常方便。
感谢 Asher Gomez 提出了此功能,感谢 Lino Le Van 实现了它。
V8 11.8 和 TypeScript 5.2.2
最后,Deno v1.37 附带了 V8 11.8 和 TypeScript 5.2.2。
还想了解更多?
信不信由你,上面列出的更改仍然没有告诉您 1.37 中所有改进之处。您可以在 GitHub 上查看 Deno 1.37 中合并的完整拉取请求列表。
感谢我们的社区贡献者!
没有社区的帮助,我们无法构建 Deno!无论是回答我们社区 Discord 服务器中的问题还是报告错误,我们都非常感谢您的支持。特别是,我们要感谢以下人员对 Deno 1.37 的贡献:Adam Powers、Alexander Michaud、Curran McConnell、Evan、Fabian、Filip Skokan、Jakub Jirutka、Jonathan Rezende、Juan Gonzalez、Kira、Kyle Kelley、Laurence Rowe、Leigh McCulloch、Marcos Casagrande、Shreyas、Valentin Anger、VlkrS、await-ovo、lionel-rowe、osddeitf、sigmaSd、zuisong、林炳权、第二扩展。
您想加入 Deno 社区贡献者的行列吗?请在此处查看我们的贡献文档,下次再见。
感谢您关注我们的 1.37 版本,希望您喜欢使用 Deno 进行构建!
🍋 您知道吗?Fresh 变得更加新鲜了。
Deno Fresh v1.4 于几周前发布,其特点是可选的 AOT 编译步骤可加快页面加载速度、异步布局、路由组等。了解更多关于 Deno 现代 Web 框架的最新版本。