Deno 的模块系统采用去中心化的设计,与 Node.js 的 npm 生态系统有显著不同。理解 Deno 的模块导入机制对于高效开发至关重要。
模块导入方式
1. URL 导入
Deno 使用 URL 直接导入模块,这是其最显著的特点:
typescript// 从 Deno 标准库导入 import { serve } from "https://deno.land/std@0.208.0/http/server.ts"; // 从第三方库导入 import { oak } from "https://deno.land/x/oak@v12.6.1/mod.ts"; // 从 GitHub 导入 import { myLib } from "https://raw.githubusercontent.com/user/repo/main/mod.ts";
2. 本地文件导入
typescript// 相对路径导入 import { utils } from "./utils.ts"; import { helper } from "../helper/helper.ts"; // 绝对路径导入 import { config } from "/app/config.ts";
3. 导入映射(Import Maps)
使用 import_map.json 管理模块别名:
json{ "imports": { "std/": "https://deno.land/std@0.208.0/", "oak": "https://deno.land/x/oak@v12.6.1/mod.ts", "@utils/": "./src/utils/" } }
使用方式:
typescriptimport { serve } from "std/http/server.ts"; import { Application } from "oak"; import { formatDate } from "@utils/date.ts";
运行时指定 import map:
bashdeno run --import-map=import_map.json app.ts
版本管理
1. 版本锁定
Deno 推荐在 URL 中指定具体版本:
typescript// 推荐:指定版本 import { serve } from "https://deno.land/std@0.208.0/http/server.ts"; // 不推荐:使用最新版本(可能不稳定) import { serve } from "https://deno.land/std/http/server.ts";
2. 依赖缓存
Deno 会缓存所有下载的模块:
bash# 查看缓存位置 deno info # 重新下载依赖 deno cache --reload app.ts # 清除缓存 deno cache --reload all
模块导出
1. 命名导出
typescript// utils.ts export const add = (a: number, b: number): number => a + b; export const subtract = (a: number, b: number): number => a - b; export interface User { id: number; name: string; }
2. 默认导出
typescript// app.ts export default class Application { start() { console.log("Application started"); } }
3. 重新导出
typescript// index.ts export * from "./utils.ts"; export { default as App } from "./app.ts"; export type { User } from "./types.ts";
权限要求
导入远程模块时,Deno 需要网络权限:
bash# 允许网络访问以下载模块 deno run --allow-net app.ts # 允许读取缓存 deno run --allow-read app.ts
与 Node.js 的对比
| 特性 | Deno | Node.js |
|---|---|---|
| 导入方式 | URL 导入 | npm 包名 |
| 依赖管理 | 无 package.json | package.json + node_modules |
| 版本控制 | URL 中的版本号 | package.json 版本范围 |
| 模块解析 | 直接 URL | node_modules 查找算法 |
| 缓存机制 | 全局缓存 | 本地 node_modules |
| 类型支持 | 原生 TypeScript | 需要 @types 包 |
最佳实践
- 始终指定版本:在 URL 中使用明确的版本号
- 使用 Import Maps:简化模块路径管理
- 依赖锁定:考虑使用
deno.lock文件 - 权限最小化:只授予必要的权限
- 缓存管理:定期清理和更新缓存
实际示例
创建一个简单的 Web 服务器:
typescript// 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 === "/") { return new Response("Hello, Deno!", { headers: { "content-type": "text/plain" }, }); } return new Response("Not Found", { status: 404 }); }; await serve(handler, { port: 8000 });
运行:
bashdeno run --allow-net server.ts
Deno 的模块系统提供了更简单、更直接的依赖管理方式,消除了 node_modules 的复杂性,同时保持了良好的类型支持和开发体验。