Deno 是一个简单、现代且安全的 JavaScript 和 TypeScript 运行时,它使用 V8 引擎并采用Rust语言开发。

相对于node.js,它具有以下好处:

  • 支持TypeScript运行时
  • 具有权限管理,对于网络/文件的读写权限需要额外声明
  • 没有node_modules,项目更加干净
  • 脚本代码能被打包为单独的JavaScript文件

安装

Deno是一个单独的二进制可执行文件,无需外部依赖

deno_install 为下载和安装二进制提供了快捷简便的脚本。

使用 Shell(macOS 和 Linux):

curl -fsSL https://x.deno.js.cn/install.sh | sh

复制

使用 PowerShell(Windows):

iwr https://x.deno.js.cn/install.ps1 -useb | iex

使用deno --version测试是否安装成功

如需更新旧版本的 Deno,你可以运行:

deno upgrade

复制

此操作会从 github.com/denoland/deno/releases 下载最新并解压,并使用解压后的文件替换你当前的可执行文件。

你也可以使用此工具来安装特定版本的 Deno:

deno upgrade --version 1.0.1

Hello Word

Demo是JavaScript/TypeScript的运行时,于浏览器环境兼容,即在deno中的一个hello word程序,在于浏览器中运行结果是相同的

可以在浏览器的dev面板 Console里执行

console.log("Welcome to Deno!");

image-20220321151043402

或是运行ts文件

deno run https://deno.land/std@$STD_VERSION/examples/welcome.ts

image-20220321151125301

发送HTTP请求

大部分程序都是使用HTTP从Web服务器上获取数据,接下来的示例是获取一个文件,并把文件内容打印到终端上。

与在浏览器环境一样,您可以使用 WEB 标准 API fetch 来发送 HTTP 请求:

const url = Deno.args[0];   //将得到的第一个参数存储到url这个常量中
const res = await fetch(url);   //向制定的url发出请求,将响应结果存储到res常量中

const body = new Uint8Array(await res.arrayBuffer());   //将响应体解析为ArrayBuffer,并将其转换为Uint8Array以存储在body常量中
await Deno.stdout.write(body);  //将body中的内容写入stdout

image-20220321152345657

运行试试看:

deno run http.ts https://example.com

image-20220321152507573

运行时候提示我们是否开启网络授权标识(--allow-net),如果不需要这个提示,需要显示地授予程序执行这些操作的权限,我们带上授权标识再试:

deno run --allow-net=example.com http.ts https://example.com

image-20220321153617123

TCP服务器

以下示例为:服务器接收8080端口上的连接,并向客户机返回它发送的任何内容

import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
const hostname = "0.0.0.0";
const port = 8080;
const listener = Deno.listen({ hostname, port });
console.log(`Listening on ${hostname}:${port}`);
for await (const conn of listener) {
  copy(conn, conn);
}

由于需要访问网络,所以命令需要导游授权标识:

deno run --allow-net https://deno.land/std@$STD_VERSION/examples/echo_server.ts

要测试它,请尝试用 netcat 向它发送数据(Windows 系统使用 telnet):

$ nc localhost 8080
hello world
hello world

命令行接口

Deno 是一个命令行程序。到目前为止,你应该熟悉一些简单的命令,并且已经了解了 shell 使用的基本知识。

这是查看主要帮助文档的几种方式:

# 使用子命令
deno help

# 使用短选项 -- 输出和上面一样
deno -h

# 使用长选项 -- 输出更详细的帮助文本(如有)
deno --help

复制

Deno 的 CLI 是基于子命令的。上面提到的帮助命令展示了一个子命令列表,比如 deno bundle。 如果你想查看 bundle 特定子命令,可以类比帮助文档的命令行,运行以下命令其中的一种:

deno help bundle
deno bundle -h
deno bundle --help

脚本来源

Deno能够从多个来源抓取脚本,比如一个文件名、一个URL或是"-"(标识从标准输入 stdin 读取)。

deno run main.ts
deno run https://mydomain.com/main.ts
cat main.ts | deno run -

脚本参数

通过在脚本名称后指定参数,您可以将用户空间参数放在最后面以传递给要运行的脚本,这些参数与 Deno 运行时选项区分开。

deno run main.ts a b -c --quiet
// main.ts
console.log(Deno.args); // [ "a", "b", "-c", "--quiet" ]

要注意,这里脚本名称之后所传递的内容都将被作为脚本参数传递,而非deno的运行时选项,对比以下两行命令:

# 正常情况:我们给 net_client.ts 授予网络权限。
deno run --allow-net net_client.ts

# 错误情况:--allow-net 传递为 Deno.args,引发网络权限错误。
deno run net_client.ts --allow-net

观察模式

--watch:启动内置的文件观察期,当Deno用这个选项启动时,它会监视:

  • 对于deno run deno testdeno bundle 入口点,入口点静态导入的所有本地文件都将被监视。

  • 对于Deno FMT,所有本地文件和目录指定为命令行参数(或如果未传递特定文件/目录,或者运行)。

只要在磁盘上更改一个被观察的文件,程序将自动重新启动/格式化/测试/捆绑。

deno run --watch main.ts
deno test --watch
deno fmt --watch

完整性检查(Lock files)

有时我们会远程引入一些URL模块,当您第一次编译模块时,将检索,编译和缓存,直到在信机器上运行或是重新载入缓存。但是如果远程的URL模块的内容发生变化了,可能导致生产模块以不同的依赖性代码运行,所以避免这种情况发生要使用完整性检查或是锁定文件

Deno可以使用小型JSON文件村和检查模块的子资源完整性。使用--lock=lock.json启用和制定锁定文件检查。使用--lock=lock.json --lock-write来更新或是创建锁定。--lock=lock.json会告诉deno使用什么锁定文件,而--locak-write永与将依赖性的哈希输出到锁定文件(--locak-write必须和--lock结合使用)

lock.json可能像这样:

{
  "https://deno.land/std@$STD_VERSION/textproto/mod.ts": "3118d7a42c03c242c5a49c2ad91c8396110e14acca1324e7aaefd31a999b71a4",
  "https://deno.land/std@$STD_VERSION/io/util.ts": "ae133d310a0fdcf298cea7bc09a599c49acb616d34e148e263bcb02976f80dee",
  "https://deno.land/std@$STD_VERSION/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a",
   ...
}

缓存和编译选项

影响可以填充缓存的命令:deno cachedeno rundeno testdeno bundledeno docdeno compile。和上面的标志一样,这也包括那些影响模块解析、编译配置等的标志。

--config <FILE>              # 加载配置文件
--import-map <FILE>          # 加载导入映射文件
--no-remote                  # 不要解析远程模块
--reload=<CACHE_BLOCKLIST>   # 重新加载源代码缓存(重新编译 TypeScript)
--unstable                   # 启用不稳定 API

运行时选项

对运行用户代码有影响的命令: deno rundeno test. 这些包括以上所有和以下内容。

权限选项,参考:https://www.denojs.cn/manual/getting_started/permissions#permissions-list

对运行环境有影响的更多选项:

--cached-only               # 要求远程依赖已经被缓存
--inspect=<HOST:PORT>       # 在 host:port 启动检查器
--inspect-brk=<HOST:PORT>   # 在 host:port 启动检查器并且暂停执行
--location <HREF>           # Value of 'globalThis.location' used by some web APIs
--seed <NUMBER>             # 指定 Math.random() 的随机种子
--v8-flags=<v8-flags>       # 设置 V8 命令行选项

Configuration file

Deno支持的配置文件允许自定义内置的TypeScript编译器、格式化器和检测器。

通过使用--config path/to/file.json告诉Deno

注意,现在不需要使用配置文件,将来也不需要。Deno仍然最好使用默认选项,没有配置文件。配置文件中指定的所有选项也可以使用命令行标志来设置(例如——options-use-tabs用于deno fmt)。使用配置文件应该被认为是一种“按需”的特性,而不是每个用户在设置项目时的第一件事。

配置文件支持.json和.jsonc扩展。我们建议使用deno.json或deno.jsonc作为文件名,因为该文件的自动查找计划用于即将发布的版本。

格式例如:

{
  "compilerOptions": {
    "allowJs": true,
    "lib": ["deno.window"],
    "strict": true
  },
  "lint": {
    "files": {
      "include": ["src/"],
      "exclude": ["src/testdata/"]
    },
    "rules": {
      "tags": ["recommended"],
      "include": ["ban-untagged-todo"],
      "exclude": ["no-unused-vars"]
    }
  },
  "fmt": {
    "files": {
      "include": ["src/"],
      "exclude": ["src/testdata/"]
    },
    "options": {
      "useTabs": true,
      "lineWidth": 80,
      "indentWidth": 4,
      "singleQuote": true,
      "proseWrap": "preserve"
    }
  }
}

权限

Deno是more安全按的。因此,除非专门启用它,程序运行时是没有文件、网络、环境的访问权限。访问安全敏感的功能,需要通过命令行标志或运行时权限提示将权限授予正在执行的脚本。

例如:

deno run --allow-read mod.ts
# mod.ts只被授予了文件系统的只读权限,无法写入或是其他敏感操作

权限列表

  • --allow-env=\:允许获取和设置环境变量,从Deno 1.9开始,您可以指定一个可选的、以逗号分隔的环境变量列表。

    deno run --allow-env=Home env.js
  • --allow-hrtime:允许高分辨率时间测量。高分辨率时间可用于定时攻击和指纹识别。

  • --allow-net=\:允许访问网络,可以指定一个可选的、用逗号分隔的IP地址或主机名列表。

    deno run -allow-net=github.com,deno.land fetch.js
  • --allow-ffi:允许加载动态库。请注意,动态库不是在沙箱中运行的,因此没有与Deno进程相同的安全限制。因此,请谨慎使用。

  • --allow-read=\:允许以只读的方式访问系统文件,可以指定一个可选的、以逗号分隔的目录或文件列表。

    deno run --allow-read=/etc main.ts
  • --allow-run=\:允许运行子程序,从Deno 1.9开始,可以指定一个可选的,以逗号分隔的子进程列表来提供一个允许的子进程列表

    deno run --allow-run=whoami run.js
  • --allow-write=\:允许文件系统写访问,可以指定可选的,逗号分隔的目录或文件列表,以提供允许的文件系统访问的允许列表

  • -A, --allow-all: 允许所有权。