跳至主要内容
Deno 2 终于来了 🎉️
了解更多
Deno 1.25 Release Notes

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

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

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

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

deno init 子命令

使用 Deno 启动新项目一直都非常简单:您只需要一个文件即可开始。无需任何配置文件、依赖项清单或构建脚本。

来自其他生态系统的用户往往不习惯这种简单性 - 他们经常寻找一个工具来搭建一个基本的项目结构,以帮助他们走上正轨。在这个版本中,我们添加了一个 deno init 子命令,它可以搭建一个基本的 Deno 项目。

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

$ deno run main.ts
Add 2 + 3 = 5

$ deno test
Check file:///dev/main_test.ts
running 1 test from main_test.ts
addTest ... ok (6ms)

ok | 1 passed | 0 failed (29ms)

该子命令将创建两个文件 (main.tsmain_test.ts)。这些文件提供了一个如何编写 Deno 程序和如何为其编写测试的基本示例。main.ts 文件导出一个 add 函数,它将两个数字加在一起,而 main_test.ts 文件包含该函数的测试。

您也可以为 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

我们很乐意听取您对该功能的反馈意见 在此 GitHub 问题中

实验性 npm 支持

此版本添加了对 npm 说明符的实验性支持。重要的是要强调,此功能仍在开发中。npm 说明符非常新,您可能会发现某些情况下它无法正常工作。请将这些问题报告给 问题跟踪器。我们将在接下来的几个版本中努力改进兼容性层和用户体验。

这些说明符的工作原理最好通过一个示例来描述

// main.ts
import express from "npm:express";
const app = express();

app.get("/", function (req, res) {
  res.send("Hello World");
});

app.listen(3000);
console.log("listening on https://127.0.0.1:3000/");

这些 npm 说明符具有以下格式

npm:<package-name>[@<version-requirement>][/<sub-path>]

然后执行以下操作将启动一个简单的 express 服务器

$ deno run --unstable --A main.ts
listening on https://127.0.0.1:3000/

执行此操作时,无需执行 npm install 也不必创建 node_modules 文件夹。这些包也受到与 Deno 应用程序相同的权限限制。但是,目前会要求一些不必要的权限,但在将来,上述程序只需要网络权限。

这些说明符目前适用于 deno rundeno testdeno bench。类型检查尚未支持。语言服务器、deno vendordeno infodeno install 的集成也尚未准备好。

npm 包二进制文件可以在没有 npm install 的情况下从命令行执行,方法是使用以下格式的说明符

npm:<package-name>[@<version-requirement>][/<binary-name>]

例如

$ deno run --unstable --allow-env --allow-read npm:[email protected] Hello there!
 ______________
< Hello there! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
$ deno run --unstable --allow-env --allow-read npm:[email protected]/cowthink What to eat?
 ______________
( What to eat? )
 --------------
        o   ^__^
         o  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

与前面的示例类似,此 npm 包需要 env 和 read 权限,但将来它不应该需要任何权限。

我们将在未来的版本中添加对 npm 包二进制文件的 deno install 和锁定文件支持。

由于该功能仍处于实验阶段,因此导入 npm 说明符时需要指定 --unstable

新的实验性 HTTP 服务器 API

Deno 1.25 引入了一个新的实验性 HTTP 服务器,旨在提供一流的 HTTP 性能。我们的基准测试 表明,与 Node.js 相比,每秒请求的 hello-world 性能提高了 4 倍,与我们现有的 Web 服务器相比,性能提高了 3 倍。新服务器甚至比规范的 Rust HTTP 服务器 Hyper 的单线程配置快 20%。

新的 Deno.serve() API 对我们现有 std/http 服务器的用户来说会非常熟悉,因为它可以作为 std/httpserve() 函数的直接替换。

现在,一个基本的 hello world 服务器就像下面一样简单

Deno.serve(() => new Response("Hello, world!"));

您可以在 doc.deno.land 上找到此 API 的完整文档。

在此示例中,每个请求都使用动态渲染的 React 组件进行响应

// ssr.jsx
import * as React from "npm:react";
import { renderToReadableStream } from "npm:react-dom/server";

const App = () => (
  <html>
    <body>
      <h1>Hello World</h1>
    </body>
  </html>
);

const options = {
  headers: {
    "Content-Type": "text/html",
  },
};

Deno.serve(
  { port: 4500 },
  async () => new Response(await renderToReadableStream(<App />), options),
);

新服务器目前只支持 HTTP/1.1。无缝 HTTP/2 支持已计划在将来的版本中添加。我们现有服务器中提供的其他功能(如自动响应主体压缩)也已计划。

此新服务器尚不应用于服务生产流量,但我们鼓励您进行尝试和基准测试。由于 API 仍处于实验阶段,因此需要使用 --unstable 标志才能使用它。请将您发现的任何错误报告给 Deno 的 问题跟踪器

在接下来的几周内,您将看到一篇关于新 HTTP 服务器性能的更详细的博文,其中包含更全面的基准测试和运行时比较。

启动时间改进

Deno 启动时,会提前分析依赖项以确保远程模块已缓存。此依赖项分析在大型文件上可能非常昂贵,因此在 Deno 1.25 中,它在后台针对每个文件进行缓存。通过此改进,如果您在初始运行后任何依赖项都包含大型文件,您应该会注意到启动时间显着提高。

例如,ts_morph 依赖于 TypeScript 编译器,该编译器作为 10 MB 的 JavaScript 文件发布。

import { Project } from "https://deno.land/x/[email protected]/mod.ts";
console.log(Project);

在 Deno 的先前版本中,以上代码在我们的一台机器上每次运行大约需要 1080 毫秒。现在,在第一次运行后,它需要大约 225 毫秒。

此外,基准内存使用量方面的回归问题已得到修复,并对内存使用量进行了其他改进。您应该会看到与最近的版本相比有明显的减少。

FFI API 改进

此版本为不稳定的 外部函数接口 添加了新功能和性能改进

Uint8Array 和 64 位数字在 Fast FFI 调用中

在 Deno v1.24 中,添加了 Fast FFI 调用,这显着提高了性能。该优化仅针对数字类型启用。

此版本为 u64i64pointerbuffer 类型启用了此快速路径。现在,许多 FFI 模块可以从 JavaScript 中舒适地实现类似本机的性能。

基准测试 使用 SQLite 的 C API 通过 Deno FFI 执行。越高越好。

新增 buffer 类型

之前,pointer 类型包括将 JS TypedArray 作为参数传递。

此版本添加了一种新类型 buffer,以利用 TypedArray 的性能优化。

const { symbols: { hash } } = Deno.dlopen("libtest.so", {
  hash: {
    parameters: ["buffer", "u32"],
    result: "u32",
  },
});

const u8 = new Uint8Array([1, 2, 3]);
hash(u8, u8.byteLength);

返回 buffer 类型与返回 pointer 类型相同。pointer 类型不再在慢速调用路径中接受 TypedArray,以鼓励使用这种新类型。

之前

cpu: Apple M1
runtime: deno 1.24.0 (aarch64-apple-darwin)

file:///deno/test_ffi/tests/bench.js
hash()    180.77 ns/iter (176.22 ns … 195.53 ns)  181.3 ns 193.97 ns 195.35 ns

之后

cpu: Apple M1
runtime: deno 1.25.0 (aarch64-apple-darwin)

file:///deno/test_ffi/tests/bench.js
hash()     56.01 ns/iter   (55.43 ns … 62.43 ns)  56.03 ns  60.02 ns  61.33 ns

Deno.UnsafePointerView API 更新

Deno.UnsafePointerView 接口中添加了三个新的静态方法

  • Deno.UnsafePointerView#getCString
  • Deno.UnsafePointerView#getArrayBuffer
  • Deno.UnsafePointerView#copyInto
const ptr = symbols.get_hello();
// Read the C String into a JS string.
const string = Deno.UnsafePointerView.getCString(ptr);

// Zero-copy AB to the pointer.
const arrayBuffer = Deno.UnsafePointerView.getArrayBuffer(ptr);

// Copying buffer
const copy = new Uint8Array(32);
Deno.UnsafePointerView.copyInto(ptr, copy);