Deno 入门与实践:安全 TypeScript 运行时
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.json 或 deno.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。
- 创建数据文件
users.json:
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
- 编写
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 });
- 运行服务(注意授予读取权限和网络权限):
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 来开发下一个项目。