Deno 入门与实践:安全 TypeScript 运行时

FreeGuideOnline 最新 2026-06-12

Deno 现代 JavaScript 运行时

Deno 是一个基于 V8 引擎的现代 JavaScript 和 TypeScript 运行时,由 Node.js 的原始作者 Ryan Dahl 创建。它在设计上修复了 Node.js 早期留下的许多架构问题,以安全性、模块化和开箱即用的开发体验为核心。本教程将带你从零开始掌握 Deno 的基本使用方法,并通过实践理解它作为安全 TypeScript 运行时的优势。

初识 Deno

Deno 被设计为一个单一可执行文件,集成了运行时、包管理器、测试运行器、代码格式化工具和类型检查器。与 Node.js 最大的不同在于:

  • 默认安全:脚本无法访问文件系统、网络或环境变量,除非显式授权。
  • 一流 TypeScript 支持:无需额外配置即可运行 .ts 文件。
  • 标准模块代替核心 API:核心功能通过经过审计的标准库提供,而非内置到运行时中。
  • 去中心化模块分发:通过 URL 或路径直接导入模块,无需 node_modules

安装 Deno

Deno 支持 Windows、macOS 和 Linux。推荐使用官方脚本安装:

# macOS / Linux
curl -fsSL https://deno.land/install.sh | sh

# Windows (PowerShell)
irm https://deno.land/install.ps1 | iex

安装完成后,验证版本:

deno --version

你也可以使用包管理器安装,如 Homebrew (brew install deno) 或 Chocolatey (choco install deno)。安装包很小,且包含所有工具。

Hello, Deno!

新建一个 main.ts 文件:

console.log("Hello, Deno!");

运行它:

deno run main.ts

你会立刻看到输出,没有 node_modules,也不需要 package.json。如果尝试读取文件或发起网络请求,Deno 会报错并提示权限,这正是其安全特性的体现。

安全权限模型

Deno 默认运行在沙盒中,必须通过命令行标志显式授权敏感操作。以下是最常用的权限标志:

权限标志 允许的操作
--allow-read[=PATH] 读取文件系统
--allow-write[=PATH] 写入文件系统
--allow-net[=HOST] 网络访问
--allow-env[=VAR] 访问环境变量
--allow-run[=CMD] 执行子进程
--allow-ffi 加载动态链接库
-A / --allow-all 所有权限(等同于关闭沙盒)

示例:运行一个需要读取网络和文件的脚本:

deno run --allow-net --allow-read=data.json app.ts

你可以在代码中动态请求权限,但这属于进阶用法。对初学者而言,最重要的一点是:永远不要随意使用 -A 标志,只为脚本授予所需的最小权限。

模块导入与标准库

Deno 使用 ESM 语法,直接从 URL 导入模块:

import { serve } from "https://deno.land/std@0.208.0/http/server.ts";

serve((_req) => new Response("Hello from Deno!"), { port: 8000 });

首次运行时,Deno 会下载并缓存这些依赖,后续运行直接从缓存读取,无需重复下载。缓存位置为 DENO_DIR 环境变量指定的路径(默认为 ~/.cache/deno)。

标准库

Deno 标准库(std)是一组经过审查的高质量模块,涵盖常用任务,如处理文件系统、HTTP、日志、路径操作等。你可以从 https://deno.land/std 导入。版本标签(如 @0.208.0)锁定了特定版本,避免破坏性变更。

第三方模块与 deno.land/x

任何可公开访问的 URL 模块都可以导入。为了更好的发现性,Deno 提供了 https://deno.land/x,一个由社区维护的第三方模块注册中心,但模块本身仍然托管在各自仓库,deno.land/x 仅作为路由。你可以直接从 GitHub 原始文件、npm(通过 npm: 前缀)或任何 CDN 导入。

深入 TypeScript 支持

Deno 原生理解 TypeScript,无需安装 typescript 或配置 tsconfig.json。你可以直接在 .ts.tsx 文件中使用 TypeScript 语法,Deno 内置了 TypeScript 编译器(SWC),编译速度快,且类型检查与运行时集成为一道命令。

如果需要类型检查而不执行代码,使用:

deno check main.ts

配置 Deno

虽然默认配置已经足够开始,但你可以通过 deno.jsondeno.jsonc(支持注释)文件自定义编译器选项、导入映射、任务、lint 规则等。例如:

{
  "compilerOptions": {
    "strict": true
  },
  "importMap": "./import_map.json",
  "tasks": {
    "dev": "deno run --allow-net main.ts"
  }
}

然后使用 deno task dev 运行。

内置开发工具

代码格式化

Deno 附带了自有的强化版本 prettier,用于格式化 JavaScript、TypeScript 和 Markdown:

deno fmt

它会格式化当前目录下所有支持的文件。还可配合 --check 在 CI 中验证格式。

测试运行器

Deno 内置测试运行器,支持异步测试、基准测试、测试步骤等。测试文件通常以 _test.ts 结尾,使用 Deno.test() API:

// math_test.ts
import { assertEquals } from "https://deno.land/std@0.208.0/assert/mod.ts";
import { add } from "./math.ts";

Deno.test("add function", () => {
  assertEquals(add(2, 3), 5);
});

运行测试:

deno test

代码打包与编译

Deno 可以将你的项目打包为单个 JavaScript 文件,或者编译为独立可执行文件。

打包(将所有依赖内联):

deno bundle main.ts bundle.js

编译为可执行文件(自包含二进制,无需安装 Deno):

deno compile --allow-net --output myapp main.ts

代码检查

Deno 内置了 Linter:

deno lint

它可以发现未使用变量、非空断言不当等常见问题,规则集持续扩充。

使用 Node.js / npm 模块

Deno 原生支持导入 npm 包,通过 npm: 前缀:

import chalk from "npm:chalk@5";
console.log(chalk.blue("Hello from npm!"));

Deno 会解析并运行 npm 包,而不需要 node_modules 或单独的包管理器。对于复杂的 npm 依赖,Deno 提供了内置的与 Node.js 兼容的 API(通过 --compat 或直接在代码中使用 node: 前缀导入 Node.js 核心模块)。

实战:构建一个简单的 REST API

让我们结合所学,创建一个简单的 HTTP 服务,它使用安全权限,从文件读取数据并返回 JSON。

  1. 创建数据文件 users.json
[
  { "id": 1, "name": "Alice" },
  { "id": 2, "name": "Bob" }
]
  1. 编写 server.ts
import { serve } from "https://deno.land/std@0.208.0/http/server.ts";

const handler = async (req: Request): Promise<Response> => {
  const url = new URL(req.url);
  if (url.pathname === "/users" && req.method === "GET") {
    const data = await Deno.readTextFile("./users.json");
    return new Response(data, {
      headers: { "content-type": "application/json" },
    });
  }
  return new Response("Not Found", { status: 404 });
};

console.log("Server running on http://localhost:8000");
serve(handler, { port: 8000 });
  1. 运行服务(注意授予读取权限和网络权限):
deno run --allow-read=./users.json --allow-net server.ts

访问 http://localhost:8000/users,你将看到用户列表。任何其他路径会返回 404。这里我们只授予了对 users.json 的读取权,即使脚本被恶意修改,也无法读取其他文件或进行未经授权的网络请求。

Deno 的任务运行器与脚本管理

Deno 通过 deno task 内置了任务运行器,定义在 deno.json 中,可以执行任意 shell 命令:

{
  "tasks": {
    "start": "deno run --allow-net --allow-read main.ts",
    "test": "deno test --allow-read=data",
    "fmt-check": "deno fmt --check"
  }
}

然后使用 deno task start 等命令。这样你可以用 Deno 替代 npm scripts,让项目更统一。

进一步学习

  • 官方手册https://deno.land/manual —— 涵盖所有细节。
  • Deno Deploy:将 Deno 程序部署到全球边缘网络,零配置。
  • 社区示例https://examples.deno.land 包含大量代码片段。

Deno 代表了现代 JavaScript 运行时的新方向:安全、零配置、拥抱标准。通过本教程,你已经掌握了安装、基础脚本、权限系统、模块导入、TypeScript 开发、内置工具以及构建一个真实 API 的流程。你可以自信地开始使用 Deno 来开发下一个项目。