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

Deno 1.34:deno compile 支持 npm 包

在我们继续朝着 Deno 2 的开发之旅前进的过程中,这个小版本主要集中在提高与 npm 和 Node.js 的兼容性,增强整体的易用性和开发人员体验,并为未来的性能增强奠定基础。

此版本中最重要的更新包括三个备受期待的功能

除了上述功能外,还有许多其他值得一提的改进和错误修复



deno compile 支持 npm 包

自从 v1.6 以来,deno compile 允许您将项目编译成单个二进制可执行文件。这项开发已被证明对许多原因至关重要,因为它使开发人员能够

  • 在所有主要平台上分发和执行二进制文件,而无需安装 Deno 或依赖项
  • 将资产包含在可执行文件中,以提高可移植性
  • 使用单个二进制文件简化部署
  • 实现更快的启动时间

从那时起,我们一直在努力使 deno compile 更加有用,通过 添加对 web 工作者和动态导入的支持,以及今天,通过支持 npm 包。

以下是用 cowsay 创建单个二进制可执行文件的示例

$ cat main.ts
import { say } from "npm:[email protected]";
console.log(say({ text: "Hello from Deno!" }));

$ deno compile --allow-read main.ts
$ ./main
 __________________
< Hello from Deno! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

cowsay 是一个简单的示例,但您可以将 deno compile 用于更复杂的项目。让我们尝试 vite

$ deno compile --allow-read --allow-write --allow-env --allow-net npm:vite
$ ./vite
  ➜  Local:   https://127.0.0.1:5173/
  ➜  Network: use --host to expose
  ➜  press h to show help

或者可能是 eslint

$ deno compile --allow-read --allow-write --allow-env --allow-net npm:eslint
$ cat .eslintrc.js
module.exports = {
    "env": {
        "es2021": true,
        "node": true
    },
    "extends": "eslint:recommended",
    "overrides": [
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {
    }
}

$ cat foo.js
function foo() {
}

$ ./eslint
/dev/foo.js
  1:10  error  'foo' is defined but never used  no-unused-vars

✖ 1 problem (1 error, 0 warnings)

使用 deno compile 创建 eslint 二进制文件与 npm install -g eslint 之间的区别在于,Deno 将 eslint 与其所有依赖项和配置一起打包到 deno 可执行文件中。这意味着生成的二进制文件确保其依赖项不会意外更改,并继续以相同的方式工作,而不会受到系统上其他依赖项的干扰。此外,我们的测试表明,从 deno compile 生成的二进制文件往往比使用本地缓存的依赖项执行同一程序启动速度更快。

还有更多工作需要完成以改进 deno compile,包括最小化二进制文件的总大小,我们打算在即将发布的版本中解决此问题。

您对 deno compile 有具体反馈吗?告诉我们

deno.json 和 CLI 标志中的通配符支持

通配符 现在在配置文件 deno.jsondeno task 和 CLI 参数中受支持,用于指定文件。通配符语法是跨平台的,因此您可以放心地在 Windows、macOS 和 Linux 上使用它。

在 **deno.json** 中,您可以使用 * 匹配路径中的任意数量的字符,使用 ? 匹配单个字符,使用 ** 匹配任意数量的目录

{
  "fmt": {
    "include": ["data/example?.txt"],
    "exclude": ["testdata/**/*.ts"]
  }
}

您也可以将通配符模式用作 **CLI 参数**。以下是用 deno fmt 的上述示例

$ deno fmt --exclude="testdata/**/*.ts" "data/example?.txt"

⚠️ 请注意,我们将通配符放在引号中,以防止 shell 展开它。

使用 **deno task** 时,除了上面的通配符语法之外,您还可以使用方括号匹配一系列字符

{
  "task": {
    "files": "echo **/*.ts",
    "data": "echo data[0-9].txt"
  }
}

带有 IP 地址的 TLS 证书

最受欢迎的功能之一终于来了。您现在可以使用包含 IP 地址的 TLS 证书。

引用 rustls 团队:

这对 Kubernetes Pod 之类的东西很有用,这些 Pod 通常使用 IP 地址而不是域名,以及对 DNS over HTTPS/TLS 的使用,它需要服务器的 IP 地址以避免对名称解析的循环依赖。

使用 Deno v1.34,任何使用 TLS 的 API 都可以使用 IP 地址。例如

const resp = await fetch("https://1.1.1.1");
console.log(await resp.text());

配置文件改进

为所有子命令排除文件或文件夹

以前,如果您想让 Deno 忽略每个子命令的文件或文件夹,您必须重复指定它

{
  "fmt": {
    "exclude": ["target/"]
  },
  "lint": {
    "exclude": ["target/"]
  },
  "test": {
    "exclude": ["target/"]
  },
  "bench": {
    "exclude": ["target/"]
  }
}

从这个版本开始,您可以使用顶级的 exclude 属性

{
  "exclude": ["target/"]
}

感谢 @scarf005 实施此功能。

nodeModulesDir 属性

现在可以在 deno.json 文件中指定 nodeModulesDir 属性,以显式启用或禁用 Deno 使用 node_modules 目录。

{
  "nodeModulesDir": true
}

如果您将 Deno 与 package.json 和 node_modules 目录一起使用,建议启用此设置,因为它将提供更好的体验。例如,启用它后,Deno 的语言服务器将使用本地 node_modules 目录进行缓存和解析包。

语言服务器改进

Deno 1.33 在语言服务器中引入了文档预加载,它在初始化时预加载工作区中的模块,以便 Deno 了解它们及其内容。

在某些情况下,默认的 1000 个文件系统条目限制要么太少要么太多,因此现在可以通过设置 deno.documentPreloadLimit 属性进行配置。

{
  "deno.enable": true,
  "deno.documentPreloadLimit": 2000
}

此外,语言服务器的内部 TypeScript 隔离的默认最大内存限制已增加到 3GB,以匹配 VS Code 中 TypeScript 的默认值。最后,可以在 VSCode 扩展中通过 deno.maxTsServerMemory 配置此限制

{
  "deno.enable": true,
  "deno.maxTsServerMemory": 3072
}

Deno API 更改

Deno.serve()

上个月,我们暗示我们计划稳定 Deno.serve() API。然而,经过深思熟虑,我们决定将稳定推迟一个月,以便使这个 API 更具前向兼容性。

Deno.serve() 的签名已更改为返回 Deno.Server 的实例,而不是 Promise<void>Deno.Server 具有 finished 属性,它是一个 Promise,当服务器关闭时(使用 AbortSignal)解析。这为以编程方式控制服务器提供了更大的灵活性。

const ac = new AbortController();
const server = Deno.serve(
  { signal: ac.signal },
  (_req) => new Response("Hello world"),
);
setTimeout(() => {
  ac.abort();
}, 1000);
await server.finished;
console.log("Server has shut down");

此外,Deno.Server 具有 ref()unref() 方法。您可以使用这些方法来控制服务器是否应保持进程处于活动状态。

Deno.createHttpClient()

此不稳定 API 现在公开了更多选项,允许对创建的客户端进行更精细的控制

const client = Deno.createHttpClient({
  // Set maximum number of idle connections in the connection pool per host to 10.
  poolMaxIdlePerHost: 10,

  // Set a timeout for idle connection being kept alive to 10s. You can disable
  // timeout all together by passing `false`.
  poolIdleTimeout: 10_000,

  // Configure if the client can use HTTP1.
  http1: false,

  // Configure if the client can use HTTP2.
  http2: true,
});

const resp = await fetch("...", { client });

Deno.FileInfo

Deno.FileInfo 接口现在包含以下新的字段

  • Deno.FileInfo.isBlockDevice
  • Deno.FileInfo.isCharDevice
  • Deno.FileInfo.isFifo
  • Deno.FileInfo.isSocket

这些字段在 Linux 和 macOS 上可用。在 Windows 上,它们始终为 null

感谢 Hirotaka Tagawa 的贡献。

对 npm 和 Node 兼容性的改进

npm 支持还有一些值得注意的改进

  • deno vendor 处理 npm 指定符,并且在遇到它们时不再报错。
  • deno task 在执行 package.json 文件中的脚本时,会运行 prepost 脚本(如果存在),类似于 npm。感谢 Marvin Hagemeister 实现此功能。

我们还为一些内置的 Node.js API 提供了 polyfill

  • crypto.createDiffieHellman
  • crypto.createDiffieHellmanGroup
  • http.Server.unref
  • Module.runMain
  • performance.markResourceTiming
  • process.release
  • worker_threads

此外,以下 N-API 符号现在可以正常工作

  • napi_async_init
  • napi_async_destroy
  • napi_add_finalizer

V8 11.5 和 TypeScript 5.0.4

最后,Deno v1.34 附带 V8 11.5 和 TypeScript 5.0.4。




查看 Deno KV,我们的全球分布式数据库,用于 Deno Deploy,现已进入测试阶段