关于 deno
Deno 是面向开发者的 JavaScript 和 TypeScript 运行时与工具链,集成包管理、格式化、代码检查、测试、类型检查和打包。它可直接运行 TypeScript,并支持现有 npm 项目文件与包。
主要功能
- 01运行 JavaScript 和 TypeScript
- 02管理 npm 与 JSR 包
- 03内置格式化、代码检查和测试
- 04类型检查与打包
- 05基于权限控制访问
适用场景
- 01无需单独构建步骤运行 TypeScript
- 02管理现有 npm 项目的依赖
- 03格式化、检查、测试并进行类型检查
- 04限制脚本对文件系统和网络的访问
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ denoland/ skills --skill deno安装后在 Claude Code 中输入/deno确认已加载。
附带文件references/CLI.md
详细介绍
Deno
一个集 JavaScript 和 TypeScript 运行时、包管理器、格式化工具、代码检查工具、测试运行器、类型检查器和打包工具于一体的二进制程序。可直接运行 TypeScript。
需要 Deno 2.9+。使用 deno --version 检查版本,使用 deno upgrade 更新。
Deno 的使用方式与 npm 和 bun 一致
Deno 并非一个需要迁移代码才能使用的独立生态系统:
deno install会读取现有的package.json并写入真正的node_modules。deno add express会从 npm 安装。未加前缀的名称默认来自 npm。deno task build会运行package.json中的scripts.build或deno.json中的tasks.build。若两者都定义了,优先使用deno.json。- Node 内置模块加不加前缀都能正常使用:
node:fs和fs都能解析。 deno main.js可运行文件。deno run是可选的。- Deno 会读取
tsconfig.json。
不要把重写导入语句、采用 JSR 或重新组织项目结构作为前提。真正的两处差异是权限以及默认不运行 npm 生命周期脚本。
单文件脚本无需构建步骤,也无需 tsconfig.json。应用和框架项目可保留原有设置。
如需转换现有项目,请参阅 migrate-to-deno 技能。
依赖管理
deno install # install everything declared
deno add express # from npm (unprefixed = npm)
deno add jsr:@std/path # from JSR
deno add -D vitest # dev dependency (package.json only)
deno remove express
deno outdated # list outdated deps
deno update # alias for `deno outdated --update`
deno update --latest # ignore existing semver ranges
deno list # declared deps + resolved versions (npm ls)
deno why express # why a package is in the tree
deno audit # vulnerability audit
deno ci # clean reproducible install for CI
dx cowsay hello # run a package binary without installing (npx)
deno ci 是 CI 命令,而非 deno install:它需要 deno.lock,会删除 node_modules,严格依据锁文件安装;若锁文件已过时,则会报错。--prod 会跳过 devDependencies。
dx 相当于 npx / bunx / pnpm dlx,也是 deno x 的别名。它运行时会禁用沙箱,因此应像对待 npx 一样谨慎。
Deno 不会安装发布不到一天的版本,以限制遭到入侵的版本造成影响的时间窗口。可使用 --min-dep-age 覆盖此设置,参数可以是分钟数(120)、ISO-8601 时长(P7D)、截止日期,或用于禁用此设置的 0:
deno add --min-dep-age=0 npm:some-package
默认不运行生命周期脚本(postinstall)——安装后原生扩展看起来无法使用时,这常常让人意外。每个项目只需批准一次:
deno approve-scripts # interactive picker
deno install --allow-scripts=npm:better-sqlite3
配置文件的存放位置
| 文件 | 内容 |
|---|---|
package.json | 依赖、脚本 |
tsconfig.json | TypeScript 编译器选项 |
deno.json | Deno 配置:fmt、lint、任务、工作区 |
将依赖放在 package.json 中——其他工具都会读取它,而且 Deno 可原生解析其中的依赖。只有在没有 package.json 时,才使用 deno.json 管理依赖,例如独立脚本或 JSR 包。同样,应优先使用 tsconfig.json,而非在 deno.json 中配置 compilerOptions,这样 tsc 和编辑器才能使用相同的设置。
提交 deno.lock。Deno 会根据现有的 package-lock.json、yarn.lock、bun.lock 或 pnpm 锁文件生成该文件,并保留版本固定信息。
node_modules 布局
Deno 使用 pnpm 的隔离布局:真实文件位于 node_modules/.deno/ 中,并通过符号链接暴露,因此包无法导入未声明的依赖。对于需要 npm 扁平提升目录树的工具:
{ "nodeModulesLinker": "hoisted" }
nodeModulesDir 仅适用于没有 package.json 的项目,因此通常不是合适的配置项。
权限
Deno 不会授予文件系统、网络、环境变量或子进程访问权限,除非明确请求。
deno run --allow-net=api.example.com --allow-read=./data main.ts
deno run -A main.ts # allow everything
| 标志 | 简写 | 授予的权限 |
|---|---|---|
--allow-read[=paths] | -R | 文件系统读取 |
--allow-write[=paths] | -W | 文件系统写入 |
--allow-net[=hosts] | -N | 网络访问 |
--allow-env[=names] | -E | 环境变量 |
--allow-sys[=apis] | -S | 操作系统信息 |
--allow-import[=hosts] | -I | 从远程主机导入 |
--allow-run[=bins] | — | 子进程 |
--allow-ffi[=paths] | — | 原生库(不稳定) |
--allow-all | -A | 所有权限 |
-S 是 --allow-sys,不是 --allow-run。每个标志都接受允许列表——
--allow-net=example.com:443 比不带参数的 --allow-net 更严格。匹配的 --deny-*
标志始终优先。
遇到 Requires net access to "..." 时,添加相应的特定权限。对于可信的第一方代码和迁移期间,使用
-A 没问题,但不适合作为提交到任务中的默认设置。
配置
Deno 会从当前目录开始向上自动查找 deno.json(或 .jsonc)。
{
"tasks": {
"dev": "deno watch -A main.ts",
"start": "deno run -A main.ts"
},
"fmt": { "exclude": ["build/"] },
"lint": { "rules": { "exclude": ["no-explicit-any"] } },
"exclude": ["build/", "dist/"]
}
顶层的 exclude 适用于每个子命令;各工具的 exclude 可进一步缩小范围。
deno.json 也接受 imports,这是一个将裸模块说明符映射到实际模块说明符的导入映射。没有
package.json 的项目可通过它声明依赖,而 JSR 包则可在声明 name、version、exports 的同时用它声明自身依赖。
工作区
npm、Yarn 和 Bun 工作区开箱即用——Deno 会直接读取 package.json 中的
"workspaces"。pnpm 是个例外:首次运行时会将 pnpm-workspace.yaml 迁移到 deno.json,之后必须重新运行。
{ "workspace": ["./packages/core", "./packages/cli"] }
成员需明确列出,或使用单层通配符("packages/*");不支持 ** 和否定模式。使用 deno task --filter '*' build 在所有成员中运行任务。
包:npm 和 JSR
优先选择 npm——生态系统集中于此,deno add express 也是常见用法。标准库(@std/*)可使用 JSR;若要发布 TypeScript,让使用者无需构建步骤即可获得类型,也可选择 JSR。两者混用没有问题。
deno add jsr:@std/path npm:express
deno doc jsr:@std/path # read a package's API from the terminal
Deno 曾使用完整 URL 导入(https://deno.land/x/...)。这些导入仍可运行,但不再推荐;要升级到现代用法,请用 deno add 添加包,然后导入裸模块说明符。
内置工具
deno fmt # format (--check for CI)
deno lint # lint (--fix, --rules)
deno test # tests (--watch, --parallel, --coverage=dir)
deno check main.ts # type-check without running
deno bench # benchmarks
deno coverage # coverage report from --coverage output
deno compile main.ts # single-file executable (--target cross-compiles)
deno doc mod.ts # docs (--html for a site)
deno info main.ts # module graph and cache info
这些工具可替代 prettier、eslint、jest/vitest、tsc 和 pkg/nexe,且无需配置或依赖——但它们并非可直接替换的工具。功能尚未完全对等,因此迁移已有项目需要投入不少工作。无需迁移: 保留 prettier、eslint 和 vitest,并使用 Deno 作为运行时和包管理器。新项目优先使用内置工具。
可使用 // deno-lint-ignore <rule>、// deno-lint-ignore-file、
// deno-fmt-ignore、// deno-fmt-ignore-file 来抑制检查。在 Markdown 中,
代码块前的 `` 可保护仅供说明、无法独立运行的代码片段。
运行代码
deno main.ts # deno run is optional
deno watch main.ts # reload on change (replaces nodemon)
deno task dev # task from package.json or deno.json
deno repl
deno eval "console.log(1)"
deno watch 会热替换模块;若失败,则会重启。它是
deno run --watch-hmr 的别名。
HTTP 服务无需依赖:
Deno.serve((_req) => new Response("Hello"));
创建新项目
建议使用脚手架,而非手动编写文件:
deno init my-project # script + test + deno.json
deno init --empty my-project # just main.ts and deno.json
deno init --lib my-lib # library laid out for JSR
deno create vite my-app # scaffold from a package initializer
deno create 相当于 npm create / yarn create,可用于相应生态系统
(如 deno create astro)。未加前缀的名称表示 npm;使用 --jsr 可选择 JSR。
发布
发布到 npm 仍可使用常规流程——运行 npm publish,或先用 deno pack 构建 tarball。deno publish 仅面向 JSR,且要求 deno.json 包含
name、version 和 exports:
deno publish --dry-run
deno publish
在 GitHub Actions 上会自动进行来源证明。deno bump-version patch 会提升版本号;在工作区根目录下,它会更新所有成员的版本号。
指南:https://docs.deno.com/runtime/reference/cli/publish/
审查 Deno 代码
- 在有作用域的授权即可满足需求的任务中提交了
-A。 deno.lock未提交,或 CI 运行的是deno install而不是deno ci。- 在包含
package.json的项目中使用内联jsr:/npm:说明符——应使用deno add,让版本只在一个地方维护。独立脚本中使用则没问题。 - 说明符未指定版本约束。
- 在存在
package.json或tsconfig.json时,仍在deno.json中配置依赖项或编译器选项。 - CI 中缺少
deno fmt --check、deno lint、deno check。
延伸阅读
- https://docs.deno.com — 运行时文档
- https://docs.deno.com/api/ —
Deno.*API 参考 references/CLI.md— 更完整的子命令和标志参考deno <subcommand> --help— 最权威且与版本相符的资料;猜测标志用法前请先查阅。