首页
/ 在 Zed 中配置 Deno 语言支持:语言服务器切换、格式化、配置补全与调试实操指南

在 Zed 中配置 Deno 语言支持:语言服务器切换、格式化、配置补全与调试实操指南

2026-09-06 18:35:26作者:瞿蔚英Wynne

本文面向在 Zed 编辑器中编写 Deno/TypeScript 代码的开发者,完整讲解如何通过官方 Deno 扩展启用 Deno Language Server、替换默认的 TypeScript 语言服务器、获得 deno.json/package.json 配置补全,以及配置 .zed/debug.json 调试会话与 .zed/tasks.json 测试任务。内容以仓库文档 docs/src/languages/deno.md 为核心骨架,并结合 Zed 源码中语言服务器解析与设置的实现细节进行补充,保证给出的配置可以直接落地、可验证。

Deno 支持概览

Zed 通过官方 Deno 扩展为 Deno 提供语言支持(扩展可通过 Zed 的 Extensions 面板搜索安装),其语言能力依赖 Deno Language Serverdeno lsp)提供:

  • 类型检查与诊断:Deno LSP 内置基于 TypeScript 编译器的语义分析;
  • 补全与跳转:对本地模块、远程模块(https://npm: 导入)提供补全、定义跳转与引用查找;
  • 格式化:通过 LSP 的 textDocument/formatting 能力实现 deno fmt 风格格式化。

从源码结构看,denotypescript-language-serverbiomeeslinttailwind 等一同被列为“可用的语言服务器”之一,例如 crates/language/src/language_settings.rs 的测试 test_resolve_language_servers 就构造了包含 deno 在内的可用服务器集合,验证名称解析逻辑。因此,让 TypeScript/JavaScript 文件使用 Deno 生态,核心工作就是把每个具体语言(JavaScript/TypeScript/TSX)的语言服务器列表切换到 deno,并把格式化交给它。

前置条件

  1. 安装 Deno CLI:确保 deno 命令在你的 PATH 中,因为 Deno Language Server、后续的调试(runtimeExecutable: "deno")与任务(deno test)都依赖该二进制。
  2. 安装 Deno 扩展:在 Zed 的扩展市场中安装 Deno 扩展,之后 deno 才会被注册为可用的语言服务器名称。

为 JavaScript / TypeScript / TSX 启用 Deno 语言服务器

Zed 对 JS/TS 家族有一套“默认语言服务器”策略。以仓库默认设置 assets/settings/default.json 为例,TypeScriptTSX 默认使用 vtsls,并显式禁用 typescript-language-server(列表中 "!typescript-language-server" 即“默认不启用”的写法),同时通过占位符 "..." 表示“其余可用服务器都启用”。

因此,当你要用 Deno LSP 处理 .ts.tsx(以及 .js)文件时,通常需要同时完成两件事:

  • lsp 段中给 deno 服务器下发初始化选项,将 deno.enable 置为 true(Deno LSP 默认不会主动接管文件,需要显式开启);
  • 在每个语言的 language_servers 列表中显式把 deno 提到前面,并禁用 typescript-language-servervtslseslint,避免多个服务器同时做类型检查/诊断造成重复报错。

可以在设置编辑器(zed::OpenSettings)的 Languages > JavaScript / TypeScript / TSX 下操作,也可以直接在 settings 文件中加入以下完整配置:

{
  "lsp": {
    "deno": {
      "settings": {
        "deno": {
          "enable": true
        }
      }
    }
  },
  "languages": {
    "JavaScript": {
      "language_servers": [
        "deno",
        "!typescript-language-server",
        "!vtsls",
        "!eslint"
      ],
      "formatter": "language_server"
    },
    "TypeScript": {
      "language_servers": [
        "deno",
        "!typescript-language-server",
        "!vtsls",
        "!eslint"
      ],
      "formatter": "language_server"
    },
    "TSX": {
      "language_servers": [
        "deno",
        "!typescript-language-server",
        "!vtsls",
        "!eslint"
      ],
      "formatter": "language_server"
    }
  }
}

关键字段语义

配置 含义 备注
lsp.deno.settings.deno.enable 是否让 Deno LSP 接管文件 true 后 Deno 才会做类型检查与补全
language_servers 中的 "deno" 显式启用并调整顺序 列表靠前 = 优先级更高
"!typescript-language-server" / "!vtsls" / "!eslint" 前缀 ! 表示“从该语言启用集合中排除” 与默认值中的 ! 前缀写法一致
formatter: "language_server" 使用该语言启用的 LSP 提供的格式化能力 等价于执行 Deno 的格式化接口
"..."(占位符) 代表“其余所有可用语言服务器” 不使用则不会自动带入 tailwind 等其余服务器

关于 ! 前缀与 "..." 占位符的精确语义,可直接在源码测试中找到验证。例如 crates/language/src/language_settings.rstest_resolve_language_servers 证明:

  • 单独 ["..."] 等于启用全部可用服务器;
  • 显式引用某个名称(如把 deno 写在后面)会改变它在结果中的顺序
  • "!name" 会把对应服务器从结果中移除
  • 列表中出现一个尚不可用的新名称会把它追加进去

再如 crates/settings_content/src/language.rs 的合并测试表明:用户在某个语言下配置的 language_servers 列表会整体替换该语言默认列表——这正是本文配置能够把默认的 vtsls 换成 deno 的机制来源。注意,!vtsls 这类“否定”条目在合并时只对该层生效,不会反向污染全局默认(同文件 crates/settings_content/src/language.rs)。

如果你的项目仍需要保留 ESLint 的某些能力,但不想让它在类型层与 Deno 冲突,可以从列表中去掉 "!eslint" 甚至去掉 "!typescript-language-server",仅保留 "!vtsls";更复杂的语言服务器与格式化组合方式(如 formatter 的可选值 "auto""language_server""prettier"、基于 code action 的 "source.fixAll.eslint" 等)参见默认设置 assets/settings/default.json 中的示例注释,以及 配置受支持的语言 文档。

为 deno.json / package.json 提供配置补全

启用 Deno LSP 只是第一步。deno.json / deno.jsonc 是 Deno 工程的重要配置文件,Zed 通过 JSON 语言服务器(json-language-server)提供它们的补全与校验。为它们绑定 JSON Schema,需要在 settings 文件中给 json-language-server 下发如下 schemas 配置:

"lsp": {
  "json-language-server": {
    "settings": {
      "json": {
        "schemas": [
          {
            "fileMatch": [
              "deno.json",
              "deno.jsonc"
            ],
            "url": "https://raw.githubusercontent.com/denoland/deno/refs/heads/main/cli/schemas/config-file.v1.json"
          },
          {
            "fileMatch": [
              "package.json"
            ],
            "url": "https://www.schemastore.org/package"
          }
        ]
      }
    }
  }
}

fileMatch 声明了该 Schema 要匹配哪些文件名,url 指向 Schema 来源:

  • deno.jsondeno.jsonc 使用 Deno 官方维护的 config-file.v1.json Schema(随 Deno 主仓库演进,url 中的 refs/heads/main 表示跟随主干);
  • package.json 使用 JSON Schema Store 的通用 package 规范,便于在 npm 项目中获得补全与校验。

配置完成后,打开 deno.json 即可获得 tasks、imports、compilerOptions 等字段的智能补全与非法值提示;若你是将 schema 通过其他方式(如语言服务器扩展)注入的,也可以忽略此节。更多 JSON Schema 配置背景参见 JSON 语言支持文档

与 Zed 内置 Schema 机制的关系

从源码结构看,Zed 自身在 crates/json_schema_store/src/json_schema_store.rs 维护了一套 zed://schemas/ 前缀的内置静态 Schema(如 tsconfig.jsonpackage.json 的本地副本)供设置文件、任务文件等使用;而本节配置的作用对象是 json-language-server 自身的 LSP 设置,面向的是项目中的普通 JSON 文件。两者互补:前者管 Zed 自己的配置界面,后者管你的 Deno/npm 工程文件。

DAP 支持:调试 Deno 程序

Zed 内置 JavaScript 调试适配器,可在 .zed/debug.json 中定义一个基于 Node 调试协议(pwa-node)的 Deno 启动配置。将以下内容加入项目根目录.zed/debug.json

[
  {
    "adapter": "JavaScript",
    "label": "Deno",
    "request": "launch",
    "type": "pwa-node",
    "cwd": "$ZED_WORKTREE_ROOT",
    "program": "$ZED_FILE",
    "runtimeExecutable": "deno",
    "runtimeArgs": ["run", "--allow-all", "--inspect-wait"],
    "attachSimplePort": 9229
  }
]

字段说明如下:

字段 含义
adapter "JavaScript" 使用 Zed 内置的 JS 调试适配器(对应 crates 中 dap 相关实现)
label "Deno" 在调试会话列表里显示的名称
request "launch" 启动(而非 attach)模式
type "pwa-node" 复用 Node.js 的 pwa-node 调试会话类型
cwd "$ZED_WORKTREE_ROOT" 工作目录 = 当前工程根目录
program "$ZED_FILE" 启动入口 = 当前激活文件(即你要调试的 .ts
runtimeExecutable "deno" deno 作为运行时,而非 node
runtimeArgs ["run", "--allow-all", "--inspect-wait"] 运行参数:run 执行脚本、--allow-all 放开权限、--inspect-wait 等待调试器接入后再执行
attachSimplePort 9229 以简单 attach 方式连接 9229 端口(Deno 默认 --inspect 端口)

关于 .zed/debug.json 的通用机制可参考 调试器文档:它应放在项目根目录并存放“配置对象数组”;Zed 也会读取 .vscode/launch.json;若要在多个项目间复用同一套调试配置,可通过命令面板调用 zed::OpenDebugTasks 打开用户级 debug.json(macOS 位于 ~/Library/Application Support/Zed/debug.json,Linux/BSD 位于 $XDG_CONFIG_HOME/zed/debug.json,Windows 位于 %APPDATA%\Zed\debug.json),其中场景会自动合并到每个工作区。

配置完成后,把当前文件切换到待调试的入口 .ts,打开“New Debug Session / 新调试会话”对话框即可看到 Deno 配置,启动后可命中断点、单步调试。

调试运行原理解读

该配置的关键在于 runtimeArgsattachSimplePort 的组合:deno run --inspect-wait 会让 Deno 进程启动后暂停等待调试器客户端在 9229 端口接入(等待期间不会先执行代码,避免错过启动期断点),而 attachSimplePort: 9229 正是让 Zed 去 attach 这个端口。相比直接 deno run,这种“启动并等待调试器”的方式对程序入口处的断点最为可靠。

Runnable 支持:把 Deno 测试接入 Zed 任务系统

deno test 接入 Zed 的任务与测试 UI,可在项目根目录的 .zed/tasks.json 中加入:

[
  {
    "label": "deno test",
    "command": "deno test -A $ZED_FILE",
    "tags": ["js-test"]
  }
]

字段说明:

  • label:任务在 UI 中的显示名;
  • command:实际执行的 shell 命令。-A 等价于 --allow-all(放开全部权限),$ZED_FILE 是 Zed 注入的环境变量,代表当前激活文件,因此该任务会运行“当前打开文件”对应的测试;
  • tags: ["js-test"]:将任务归类为 JS 测试任务,使其出现在 Zed 的测试运行器(Run Tests)相关入口中,配合 js-test/js-test-single 等标签可实现可发现性与一键执行。

配置后可打开的交互入口包括:命令面板中的 Run Task、编辑器上下文、以及测试相关面板;Zed 的任务定义与 $ZED_* 变量体系详见 tasks 相关文档 中对 cwd 默认取 $ZED_WORKTREE_ROOT、构建任务可引用 $ZED_FILE 的说明。同理,若只想针对当前文件运行单个测试,可将命令改为 deno test -A --filter <pattern> $ZED_FILE,并把 pattern 动态拼接进命令。

常见问题与调试建议

  • 切换后仍出现 vtsls 报错:确认各语言的 language_servers 中确实保留了 "!vtsls" / "!typescript-language-server" 条目;用户级配置的列表会整体替换语言默认列表(合并语义见上文源码测试),若只写了 ["deno", "..."],则其余服务器仍会参与。
  • deno.json 没有补全:确认 json-language-serverschemas 已配置且文件名与 fileMatch 完全一致(注意 deno.jsoncdeno.json 都要列出);也可在 Languages 设置中检查 JSON 语言是否启用了 json-language-server
  • 调试启动即报“找不到模块/权限错误”:检查 deno 是否在 PATH 中、cwd 是否解析到工程根目录;需要网络下载依赖时建议保留 --allow-all 或收敛为 --allow-net 等最小权限集。
  • 任务里 $ZED_FILE 为空:该变量只有在“编辑器中有激活文件”的任务触发路径下才有值;从全局(无文件)上下文触发的任务请改用 $ZED_WORKTREE_ROOT 定位文件。

相关文档

登录后查看全文
热门项目推荐
相关项目推荐