了不起的 Deno 入门篇
本文于414天之前发表,文中内容可能已经过时。
创建了一个 “重学TypeScript” 的微信群,想加群的小伙伴,加我微信 “semlinker”,备注 “1” 。阿里、京东、腾讯的大佬都在群里等你哟。
一、Deno 简介
Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码,有着卓越的开发体验。Deno 含有以下功能亮点:
默认安全。外部代码没有文件系统、网络、环境的访问权限,除非显式开启。
支持开箱即用的 TypeScript 的环境。
只分发一个独立的可执行文件(deno)。
- 有着内建的工具箱,比如一个依赖信息查看器(deno info)和一个代码格式化工具(deno fmt)。
- 有一组经过审计的 标准模块,保证能在 Deno 上工作。
- 脚本代码能被打包为一个单独的 JavaScript 文件。
Deno 是一个跨平台的运行时,即基于 Google V8 引擎的运行时环境,该运行时环境是使用 Rust 语言开发的,并使用 Tokio 库来构建事件循环系统。Deno 建立在 V8、Rust 和 Tokio 的基础上,它的架构如下:
(图片来源:https://deno.land/manual/contributing/architecture)
1.1 Rust
Rust 是由 Mozilla 主导开发的通用、编译型编程语言。设计准则为 “安全、并发、实用”,支持函数式、并发式、过程式以及面向对象的编程风格。Deno 使用 Rust 语言来封装 V8 引擎,通过 libdeno
绑定,我们就可以在 JavaScript 中调用隔离的功能。
1.2 Tokio
Tokio 是 Rust 编程语言的异步运行时,提供异步事件驱动平台,构建快速,可靠和轻量级网络应用。利用 Rust 的所有权和并发模型确保线程安全。Tokio 构建于 Rust 之上,提供极快的性能,使其成为高性能服务器应用程序的理想选择。在 Deno 中 Tokio 用于并行执行所有的异步 IO 任务。
1.3 V8
V8 是一个由 Google 开发的开源 JavaScript 引擎,用于 Google Chrome 及 Chromium 中。V8 在运行之前将JavaScript 编译成了机器代码,而非字节码或是解释执行它,以此提升性能。更进一步,使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript 程序与 V8 引擎的速度媲美二进制编译。在 Deno 中,V8 引擎用于执行 JavaScript 代码。
二、安装 Deno
Deno 能够在 macOS、Linux 和 Windows 上运行。Deno 是一个单独的可执行文件,它没有额外的依赖。你可以通过以下方式来安装它:
- 使用 Shell (macOS 和 Linux):
1 | curl -fsSL https://deno.land/x/install/install.sh | sh |
- 使用 PowerShell (Windows):
1 | iwr https://deno.land/x/install/install.ps1 -useb | iex |
- 使用 Scoop (Windows):
1 | scoop install deno |
- 使用 Chocolatey (Windows):
1 | choco install deno |
- 使用 Homebrew (macOS):
1 | brew install deno |
- 使用 Cargo (Windows,macOS,Linux):
1 | cargo install deno |
Deno 也可以手动安装,只需从 github.com/denoland/deno/releases 下载一个 zip 文件。它仅包含一个单独的可执行文件。在 macOS 和 Linux 上,你需要为它设置执行权限。当你成功安装之后,可以通过执行 deno --version
命令来查看已安装的 Deno 版本:
1 | deno --version |
2.1 deno_install
在安装过程中,如果遇到问题的话,大家可以试试 justjavac(迷渡)大神提供的安装脚本 —— deno_install。该脚本通过单行命令将 Deno 安装到系统中(国内加速)。
2.1.1 安装最新版
使用 Shell:
1 | curl -fsSL https://x.deno.js.cn/install.sh | sh |
使用 PowerShell:
1 | iwr https://x.deno.js.cn/install.ps1 -useb -outf install.ps1; .\install.ps1 |
2.1.2 安装某个特定版本
使用 Shell:
1 | curl -fsSL https://x.deno.js.cn/install.sh | sh -s v0.41.0 |
使用 PowerShell:
1 | iwr https://x.deno.js.cn/install.ps1 -useb -outf install.ps1; .\install.ps1 v0.41.0 |
更多详细的信息可以浏览 x.deno.js.cn 站点。
2.2 deno-cli
deno-cli 命令行界面提供了一组集成功能,让你可以沉浸在 Deno 的专有开发环境中。以下是 Deno 1.0.0 版本支持的所有子命令:
1 | SUBCOMMANDS: |
2.3 REPL
在命令中输入 deno 命令,你就会启动一个 REPL(Read-Execute-Print-Loop):
1 | deno |
2.4 VSCode Deno extension
相信很多小伙伴都在使用 VSCode IDE 进行前端开发,对于学习和开发 Deno 的开发者来说,一定不能错过 justjavac(迷渡) 大神开发的 Visual Studio Code Deno extension。
2.4.1 未安装 Deno extension
如果我们写 from "./hello.ts"
这样的语句,在 VSCode 中将会出现波浪号的错误信息。因为默认情况下,TypeScript 项目不需要添加 .ts
扩展名。
ts(2691): An import path cannot end with a ‘.ts’ extension. Consider importing ‘./hello’ instead.
Deno 允许从 URL 中导入模块,但是 TypeScript 并不支持从 URL 中导入模块。
ts(2307): Cannot find module ‘https://deno.land/x/std/log/mod'.
2.4.2 已安装 Deno extension
Deno 将远程导入(imports)缓存在 $DENO_DIR
环境变量指定的特殊目录中。如果未指定 $DENO_DIR
,则默认为系统的缓存目录。
该插件可以将远程导入(remote imports)解析为本地路径。
(本章节图片来源:https://marketplace.visualstudio.com/items?itemName=justjavac.vscode-deno)
了解 VSCode Deno extension 更多的详细信息,可以阅读 justjavac(迷渡) 大佬 我为 VS Code 开发了一个 Deno 插件 这篇文章。
三、Deno 初体验
3.1 welcome demo
相信一些读者安装完 Deno 已经迫不及待了,现在我们立马来体验一下 Deno 应用程序。首先打开你熟悉的命令行,然后在命令行输入以下命令:
1 | deno run https://deno.land/std/examples/welcome.ts |
通过观察以上输出,我们可以知道当运行 deno run https://deno.land/std/examples/welcome.ts
命令之后,Deno 会先从 https://deno.land/std/examples/welcome.ts
URL 地址下载 welcome.ts
文件,该文件的内容是:
1 | console.log("Welcome to Deno 🦕"); |
当文件下载成功后,Deno 会对 welcome.ts
文件进行编译,即编译成 welcome.ts.js
文件,然后再通过 V8 引擎来执行编译生成的 JavaScript 文件。需要注意的是,如果你在命令行重新运行上述命令,则会执行缓存中已生成的文件,并不会再次从网上下载 welcome.ts
文件。
1 | deno run https://deno.land/std/examples/welcome.ts |
那如何证明再次执行上述命令时, Deno 会优先执行缓存中编译生成的 JavaScript 文件呢?这里我们要先介绍一下 deno info
命令,该命令用于显示有关缓存或源文件相关的信息:
1 | deno info |
在上述的输出信息中,我们看到了 TypeScript compiler cache 这行记录,很明显这是 TypeScript 编译器缓存的目录,进入该目录后,通过一层层的查找,我们最终在 examples
目录下找到了 welcome.ts.js
文件:
1 | ➜ examples ls |
打开目录中 welcome.ts.js
文件,我们可以看到以下内容:
1 | ; |
下面我们来修改该文件,在文件中添加一行输出信息 console.log("Hello Semlinker, from Cache");
,具体如下:
1 | ; |
接着我们在命令行中重新执行以下命令:
1 | deno run https://deno.land/std/examples/welcome.ts |
那么现在问题又来了,如何强制刷新缓存,即重新编译 TypeScript 代码呢?针对这个问题,在运行 deno run
命令时,我们需要添加 --reload
标志,来告诉 Deno 需要重新刷新指定文件:
1 | deno run --reload https://deno.land/std/examples/welcome.ts |
除了 --reload
标志之外,Deno run 命令还支持很多其他的标志,感兴趣的读者可以运行 deno run --help
命令来查看更多的信息。
3.2 TCP echo server
前面我们已经介绍了如何运行官方的 welcome 示例,下面我们来介绍如何使用 Deno 创建一个简单的 TCP echo 服务器。首先我们创建一个 learn-deno 项目,然后在该项目下新建一个 quickstart 目录,接着新建一个 echo_server.ts
文件并输入以下代码:
1 | const listener = Deno.listen({ port: 8080 }); |
for await…of 语句会在异步或者同步可迭代对象上创建一个迭代循环,包括 String,Array,Array-like 对象(比如 arguments 或者 NodeList),TypedArray,Map, Set 和自定义的异步或者同步可迭代对象。
for await…of 的语法如下:
1
2
3
4 > for await (variable of iterable) {
> statement
> }
>
输入完以上代码之后,相信很多读者会跟我一样,直接在命令行运行以下命令:
1 | ➜ quickstart deno run ./echo_server.ts |
很明显是权限错误,从错误信息中,Deno 告诉我们需要设置 --allow-net
标志,以允许网络访问。为什么会这样呢?这是因为 Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码。下面我们添加 --allow-net
标志,然后再次运行 echo_server.ts
文件:
1 | ➜ quickstart deno run --allow-net ./echo_server.ts |
当服务器成功运行之后,我们使用 nc
命令来测试一下服务器的功能:
1 | ➜ ~ nc localhost 8080 |
介绍完如何使用 Deno 创建一个简单的 TCP echo 服务器,我们再来介绍一下如何使用 Deno 创建一个简单的 HTTP 服务器。
3.3 HTTP Server
与 TCP Server 一样,在 quickstart 目录下,我们新建一个 http_server.ts
文件并输入以下内容:
1 | import { serve } from "https://deno.land/std@v0.50.0/http/server.ts"; |
友情提示:在实际开发过程中,你可以从 https://deno.land/std 地址获取所需的标准库版本。示例中我们显式指定了版本,当然你也可以不指定版本,比如这样:https://deno.land/std/http/server.ts 。
在上述代码中,我们导入了 Deno 标准库 http 模块中 serve 函数,然后使用该函数快速创建 HTTP 服务器,该函数的定义如下:
1 | // std/http/server.ts |
serve 函数接收一个参数,其类型是 string | HTTPOptions
,其中 HTTPOptions 接口的定义如下:
1 | /** Options for creating an HTTP server. */ |
当输入的参数类型是字符串时,serve 函数会使用 :
冒号对字符串进行切割,获取 hostname 和 port,然后包装成对象赋值给 addr 参数,接着使用 addr 参数继续调用 listen
函数进一步创建 listener
对象,最终调用 new Server(listener)
创建 HTTP 服务器。
创建完 HTTP 服务器,我们来启动该服务器,打开命令行输入以下命令:
1 | ➜ quickstart deno run --allow-net ./http_server.ts |
接着打开浏览器,在地址栏上输入 http://localhost:8080/ 地址,之后在当前页面中会看到以下内容:
1 | Hello World\n |
四、调试 Deno
Deno 支持 V8 Inspector Protocol。使用 Chrome Devtools 或其他支持该协议的客户端(比如 VSCode)能够调试 Deno 程序。要启用调试功能,用 --inspect
或 --inspect-brk
选项运行 Deno,对应的选项描述如下:
1 | --inspect=<HOST:PORT> |
--inspect
选项允许在任何时间点连接调试器,而 --inspect-brk
选项会等待调试器连接,在第一行代码处暂停执行。
4.1 Chrome Devtools
让我们用 Chrome 开发者工具来调试一个简单的程序,我们将使用来自 std
的 file_server.ts,这是一个简单的静态文件服务。
使用 --inspect-brk
选项,在第一行代码处暂停执行。
1 | deno run --inspect-brk --allow-read --allow-net https://deno.land/std@v0.50.0/http/file_server.ts |
打开 chrome://inspect
,点击 Target 旁边的 Inspect
。
进一步了解更详细的调试说明,可访问 https://deno.land/manual/tools/debugger URL 地址。
4.2 VSCode
Deno 可以在 VSCode 中调试。插件的官方支持正在开发中 https://github.com/denoland/vscode_deno/issues/12,当然我们也可以通过手动提供 launch.json
配置,来连接调试器:
1 | { |
注意:将 <entry_point>
替换为实际的脚本名称。
下面让我们来尝试一下调试本地源文件,创建 server.ts
:
1 | import { serve } from "https://deno.land/std@v0.50.0/http/server.ts"; |
将 <entry_point>
改为 server.ts
,然后运行。
(图片来源:https://deno.land/manual/tools/debugger)
(图片来源:https://deno.land/manual/tools/debugger)
若想进一步了解 Deno 与 Node.js 的 区别,可以阅读 超杰_ Deno 正式发布,彻底弄明白和 node 的区别 这篇文章。
欢迎小伙伴们订阅全栈修仙之路,及时阅读 TypeScript、Node/Deno、Angular 技术栈最新文章。
