deno.com
在当前页面

Deno 1.x 到 2.x 迁移指南

虽然我们在 Deno 1.x 中取得了许多成就,但下一个主要版本的重点是 大规模 使用 Deno。这意味着与 Node.js 和 npm JavaScript 基础设施的无缝互操作性,并支持更广泛的项目和开发团队,同时不牺牲开发者喜爱的简单性、安全性和“开箱即用”的特性。

与 Node.js 和 npm 的向后兼容性 Jump to heading

Deno 2 与 Node.js 和 npm 向后兼容。这不仅允许你在当前的 Node.js 项目中运行 Deno,还可以逐步采用 Deno 的一体化工具链。

例如,你可以在 Node.js 项目中使用 deno install 来安装依赖项,运行 deno fmt 来格式化代码而无需 Prettier,或使用 deno lint 来检查常见问题,而无需使用 ESLint。

Deno 2 理解 package.jsonnode_modules 目录,甚至 npm 工作区,允许你以最小的努力迁移现有的 ESM 项目。

为了更好的 Node 兼容性,当存在 package.json 时,npm 包不再默认安装,而是建议运行 deno install。要获得 Deno 1.x 的自动安装行为,请在 deno.json 中添加以下内容:

deno.json
{
  "nodeModulesDir": "auto"
}

阅读更多关于 Node.js 支持 的页面

长期支持版本 Jump to heading

从 Deno v2.1.0(将于 2024 年 11 月发布)开始,Deno 将提供 LTS(长期支持)渠道。

LTS 版本将支持 6 个月,在此期间会收到错误修复和关键性能修复,然后新版本将被提升为 LTS。

阅读更多关于 稳定性和发布 的页面

管理依赖项 Jump to heading

Deno 2 通过以下工具大大改善了 npm 和 JSR 包的依赖管理:

你可以期待在使用 deno.json 的 Deno 优先项目、使用 package.json 的 Node.js 优先项目以及同时使用 deno.jsonpackage.json 的混合项目中获得无缝体验,从而实现轻松的迁移路径。

Monorepo、工作区和私有注册表支持 Jump to heading

Deno 2 是为处理关键任务的开发团队而构建的。这些团队处理复杂的代码库,共享内部代码,通常使用私有注册表。

使用 Deno 2,你的团队可以像使用 Node.js 和 npm 一样利用私有 npm 注册表,使用 .npmrc 文件:

.npmrc
@mycompany:registry=http://mycompany.com:8111/
mycompany.com:8111/:_authToken=token

了解更多关于私有注册表配置的信息,请访问 npm 包 页面

Deno 2 支持工作区,允许你在同一个 monorepo 中混合使用 Deno 优先和 Node 优先的包,使增量迁移变得快速且易于实现。

阅读更多关于 工作区和 Monorepo 的页面

框架支持 Jump to heading

随着 Node.js 和 npm 兼容性的改进,Deno 2 支持大量用户喜爱的框架,例如:

  • Next.js
  • SvelteKit
  • Remix
  • Nuxt
  • TanStack
  • Qwik
  • 以及更多

大多数现有项目只需进行最小改动或无需改动;只需将 npm run dev 替换为 deno task dev 即可继续工作。

Deno 将提供有用的错误消息和建议,引导你找到可行的解决方案。

你还可以使用 deno lint --fix 自动修复常见的不兼容问题。


以下部分概述了 Deno 1.x 和 Deno 2 之间的配置、CLI 和 API 变化。

配置变化 Jump to heading

  • nodeModulesDir

使用布尔值配置 nodeModulesDir--node-modules-dir 选项已被弃用,取而代之的是从多个行为选项中选择。因此,未设置该选项时的默认值已更改。

- "nodeModulesDir": false | true
+ "nodeModulesDir": "none" | "auto" | "manual"

- 没有 package.json 时的默认值:false(对应 "none")
+ 没有 package.json 时的默认值:"none"

- 有 package.json 时的默认值:true(对应 "auto")
+ 有 package.json 时的默认值:"manual"

如果你的项目不包含 package.json 文件,默认行为将保持不变。

如果你的项目包含 package.json 文件且未指定 nodeModulesDir 选项,则必须将其设置为 auto 以保持 Deno 1.x 的自动安装行为。Deno 2 中的新默认值是 manual,它期望用户手动保持该目录的最新状态。

请参考 Node 模块目录 了解更多信息。

CLI 变化 Jump to heading

  • deno bundle

deno bundle 命令已被移除。我们建议使用 esbuildesbuild-deno-loader

import * as esbuild from "npm:esbuild";
import { denoPlugins } from "jsr:@luca/esbuild-deno-loader";

const result = await esbuild.build({
  plugins: [...denoPlugins()],
  entryPoints: ["https://deno.land/std@0.185.0/bytes/mod.ts"],
  outfile: "./dist/bytes.esm.js",
  bundle: true,
  format: "esm",
});

esbuild.stop();
  • deno cache

deno cache 命令已合并到 deno install 命令中,作为 --entrypoint 选项。

- deno cache main.ts
+ deno install --entrypoint main.ts
  • deno vendor

deno vendor 命令已被 deno.json 中的 "vendor": true 配置选项取代。

deno.json
{
  "vendor": true
}
  • --allow-none

使用 --permit-no-files CLI 标志代替。

- deno test --allow-none
+ deno test --permit-no-files
  • --jobs

使用 DENO_JOBS 环境变量代替。

- deno test --jobs=4 --parallel
+ DENO_JOBS=4 deno test --parallel
  • --ts

使用 --ext=ts CLI 标志代替。

- deno run --ts script.ts
+ deno run --ext=ts script.ts
- deno run -T script.ts
+ deno run --ext=ts script.ts
  • --trace-ops

使用 --trace-leaks CLI 标志代替。

- deno test --trace-ops
+ deno test --trace-leaks
  • --unstable

使用细粒度的不稳定标志(--unstable-*)或配置选项代替。请参考 不稳定功能标志 了解更多信息。

// kv.ts
const kv = await Deno.openKv();

// ...
- deno run --unstable kv.ts
+ deno run --unstable-kv kv.ts

{
+ "unstable": ["kv"]
}

请参阅 Deno 1.40 博客文章 了解更多细节。

API 变化 Jump to heading

  • Deno.Buffer

使用标准库中的 Buffer 代替。

+ import { Buffer } from "jsr:@std/io/buffer";

- const buffer = new Deno.Buffer();
+ const buffer = new Buffer();

  // ...

请参阅 [deno#9795][deno#9795] 了解更多细节。

  • Deno.Closer

使用标准库中的 Closer 代替。

+ import type { Closer } from "jsr:@std/io/types";

- function foo(closer: Deno.Closer) {
+ function foo(closer: Closer) {
  // ...  
}

请参阅 [deno#9795][deno#9795] 了解更多细节。

  • Deno.close()

使用资源上的 .close() 方法代替。

test

  const conn = await Deno.connect({ port: 80 });

  // ...


- Deno.close(conn.rid);
+ conn.close();
  const file = await Deno.open("/foo/bar.txt");

  // ...

- Deno.close(file.rid);
+ file.close();

请参阅 [Deno 1.40 博客文章][Deno 1.40 blog post] 了解更多细节。

  • Deno.Conn.prototype.rid

使用 Deno.Conn 实例方法代替。

  const conn = await Deno.connect({ port: 80 });

  const buffer = new Uint8Array(1_024);
- await Deno.read(conn.rid, buffer);
+ await conn.read(buffer);

  const data = new TextEncoder().encode("Hello, world!");
- await Deno.write(conn.rid, data);
+ await conn.write(data);

- await Deno.shutdown(conn.rid);
+ await conn.closeWrite();

- Deno.close(conn.rid);
+ conn.close();

请参阅 [Deno 1.40 博客文章][Deno 1.40 blog post] 了解更多细节。

  • Deno.ConnectTlsOptions.certChain

使用 cert 选项代替。

const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
using conn = await Deno.connectTls({
  hostname: "192.0.2.1",
  port: 80,
  caCerts: [caCert],
- certChain: Deno.readTextFileSync("./server.crt"),
+ cert: Deno.readTextFileSync("./server.crt"),
  key: Deno.readTextFileSync("./server.key"),
});

请参阅 deno#22274 了解更多细节。

  • Deno.ConnectTlsOptions.certFile

使用 cert 选项代替。

const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
using conn = await Deno.connectTls({
  hostname: "192.0.2.1",
  port: 80,
  caCerts: [caCert],
- certFile: "./server.crt",
+ cert: Deno.readTextFileSync("./server.crt"),
  key: Deno.readTextFileSync("./server.key"),
});

请参阅 deno#22274 了解更多细节。

  • Deno.ConnectTlsOptions.privateKey

使用 key 选项代替。

const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
using conn = await Deno.connectTls({
  hostname: "192.0.2.1",
  port: 80,
  caCerts: [caCert],
  cert: Deno.readTextFileSync("./server.crt"),
- keyFile: "./server.key",
+ key: Deno.readTextFileSync("./server.key"),
});

请参阅 deno#22274 了解更多细节。

  • Deno.copy()

使用标准库中的 copy() 代替。

+ import { copy } from "jsr:@std/io/copy";

  using file = await Deno.open("/foo/bar.txt");

- await Deno.copy(file, Deno.stdout);
+ await copy(file, Deno.stdout);

请参阅 [deno#9795][deno#9795] 了解更多细节。

  • Deno.customInspect

使用 Symbol.for("Deno.customInspect") 代替。

class Foo {
- [Deno.customInspect]() {
+ [Symbol.for("Deno.customInspect")] {
  }
}

请参阅 deno#9294 了解更多细节。

  • Deno.fdatasync()

使用 Deno.FsFile.prototype.syncData() 代替。

  using file = await Deno.open("/foo/bar.txt", { read: true, write: true });

  await file.write(new TextEncoder().encode("Hello, world!"));
- await Deno.fdatasync(file.rid);
+ await file.syncData();
  • Deno.fdatasyncSync()

使用 Deno.FsFile.prototype.syncDataSync() 代替。

  using file = Deno.openSync("/foo/bar.txt", { read: true, write: true });

  file.writeSync(new TextEncoder().encode("Hello, world!"));
- Deno.fdatasyncSync(file.rid);
+ file.syncDataSync();
  • Deno.File

使用 Deno.FsFile 代替。

- function foo(file: Deno.File) {
+ function foo(file: Deno.FsFile) {
  // ...
}

请参阅 deno#13661 了解更多细节。

  • Deno.flock()

使用 Deno.FsFile.prototype.lock() 代替。

  using file = await Deno.open("/foo/bar.txt");

- await Deno.flock(file.rid);
+ await file.lock();

请参阅 deno#22178 了解更多细节。

  • Deno.flockSync()

使用 Deno.FsFile.prototype.lockSync() 代替。

  using file = Deno.openSync("/foo/bar.txt");

- Deno.flockSync(file.rid);
+ file.lockSync();

请参阅 deno#22178 了解更多细节。

  • Deno.FsFile.prototype.rid

使用 Deno.FsFile 实例方法代替。

  const file = await Deno.open("/foo/bar.txt");

  const buffer = new Uint8Array(1_024);
- await Deno.read(file.rid, buffer);
+ await file.read(buffer);

  const data = new TextEncoder().encode("Hello, world!");
- await Deno.write(file.rid, data);
+ await file.write(data);

- Deno.close(file.rid);
+ file.close();
  • Deno.fstatSync()

使用 Deno.FsFile.prototype.statSync() 代替。

  using file = Deno.openSync("/foo/bar.txt");

- const fileInfo = Deno.fstatSync(file.rid);
+ const fileInfo = file.statSync();

请参阅 [Deno 1.40 博客文章][Deno 1.40 blog post] 了解更多细节。

  • Deno.fstat()

使用 Deno.FsFile.prototype.stat() 代替。

  using file = await Deno.open("/foo/bar.txt");

- const fileInfo = await Deno.fstat(file.rid);
+ const fileInfo = await file.stat();

请参阅 [Deno 1.40 博客文章][Deno 1.40 blog post] 了解更多细节。

  • Deno.FsWatcher.prototype.rid

使用 Deno.FsWatcher 实例方法代替。

  using watcher = Deno.watchFs("/dir");

  // ...

- Deno.close(watcher.rid);
+ watcher.close();

请参阅 [Deno 1.40 博客文章][Deno 1.40 blog post] 了解更多细节。

  • Deno.fsync()

使用 [`Den

你找到需要的内容了吗?

隐私政策