对 Deno 感爱好,想尝尝鲜或快速入门 Deno 的小伙伴看过来,本文将从七个方面下手,带你一步步学习 Deno 的相关知识,具体的内容纲要如下图所示:
自从 Deno 1.0 正式发布之后,Deno 的热度逐步褪去。但近期 Deno 团队方案「删除全部内部代码构建d & B时的 TS 类型查看与绑T j I 2缚」,又把 Deno 再一次带入我们的视界。
下面我们来经过知乎上 「justjavac(迷渡大大)」 一个H e 0 j I 7高赞的答复来大致了解一下其主要原因。
❝
来自 「天猪」 的发问:怎样点评 deno 方案把一些内部模块从 ts 改回 js ?
来自 「justjavac( 4 D z [ + r」 的高赞答复:
先说原因:根本原因是 「ts 无法( 8 = e / C R * 2为 Deno runtimef u ^ e 生成高功用的 js 代码」。
首要需求弄清一个误区:「Deno 并没有扔掉 TypeSo p I : @ a . . Acript,Deno 依然是一个安全的 TS/JS runtime。」
编译速度慢是一个方面,但不是根` n 2 a O R % &本原因。rustc 的编译速度也很慢,但是生成的代码质量很高。tsc 确实也慢,假设 tsc 可以生成高功用的 js! 0 f 3 j J ] 代码,那么这点构建的时间成本是可以承受的。 # C但是现在来看 ts 无法为 Deno runtime 生成高功用的 js 代码。或许说,Den/ s 5 m A l B 7 Io 团队没有找到 ts 生成高功用 js 代码的办法。
Denog ^ w / : W @ ; [ 运用最新版 ts 和 v8,而 ts 和 v8 的结束方针都是 stage3,理论L b : x ; # 4上f U ] , H B 7 ts 只需简略的做类型擦除就可以直接工作在 v8 上。开端 Deno: } Z g ! $ ~ ~ 团队也是这么想的。但是实践运用+ S . 6 v ( ts 的情况却不是这么抱负。
此处省掉许多个字,这儿就不继续 “转移” 了,感爱好的小伙伴可以仔细阅读一下原文,文中 「justjavac」 具体介绍了来龙去脉。
原文地址:https://www.zhihu.com/question/402887743/answer/1297418368
❞
一、Deno 简介
Deno 是一个 JavaScript/TypeScript 的工作时,默许运用安全环境实行代码,有着卓越的开发领会。
(图片来历:hS M $ Tttps://deno.land/artwork)
Deno 是 Node.js 之父 Ryan Dahl 的另一个高文,它跟 Node.js 的联系是这样的j P I a w | Y:
"nod^ s t y & G {e".spliU ~ ; Y @ p = Lt("").sort().join(""); // Output: deno
那么实践上 Deno 与 Node.js 之间? p u P Y E K N有什么差异呢?这儿阿宝哥就不翻开介绍了,感爱好的小伙伴可以阅读 “ Deno 正式发布,完全弄理解和 node 的差异” 这篇文章。
下面我们步入正题,P O . O d [ w开端进入 Deno 的国际,Deno 含有以下功用特性:
-
默许安全,外部代码没有文件系统、网络、环境的访问权限,除非显式打开。
-
支撑开箱即用的 TypeSG A y a V 9 , 9cript 的环境。: 1 7 * u G
-
只分发一个独立的可实行文件(deno)。
-
有着内建的东西箱,比方一个依托信息查看器(deno info)和一个代码格式化东西(deno fmt)。
-
有一组经过审计的标准模块,确保能在 Deno 上作业。
-
脚本代码能被打包为一个独自的 JavaScript 文件。
Deno 是p [ X L n w一个跨途径的工作时,即依据 Google V8 引擎的工作时环境,该工作时环境是运用 Rust 言语开发的,并运用 Tokio 库来构建工作循环系统。Deno 建立在 V8、Rust 和 Tokio 的根底上,它的架构如下:
(图片来历:https://deno.land/manual/contributing/architecture)
1.1c % 9 7 R 1 Rust
Rust 是由 Mozilla 主导开发的通用、编译Y h M h H K X型编程言语。规划准则为 “安全、并发、有用”,支撑函数式、并发式、过程式以及面向方针的编程风格。Deno 运用 Rust 言语来封装 V8 引擎,经过 libdeno
绑定,我们就可以在N S 6 / JavaScript 中调用阻隔的功用。
1.2 Tokio
Tokio 是 Rust 编程言语的异步工作时,供应异步工作驱动途径,构建快速,牢靠和轻量级网络运用。运用 Rust 的全部权和并发模型确保线程安全。Tokio 构建于 Rust 之上,供应极快的功用,使其成为高功用服务器运用程序的抱负选择。在 Deno 中 Tokio 用于并行实行一X y d切的异步 IO 任务。
1.3 V8
V8 是一个由 Google 开发的开源 JavaScript 引擎,用于 Google ChroA / & U lme 及 ChroU umium 中。V8 在工作之前将JavaScript 编译成, s Q 2 e d了机器代码,而非字节码或是说明实行它,以此提升功用。更进一步,运用了如内联缓g N } –存(inline caching)等办法来提高功用。有了这些功用,JavaScript 程序与 V8 引擎的速度媲美二进制编译。在 Deno 中,V8 引擎用于h = k / $ , k实行 JavaScripT o @ S / } S . zt 代码。
二、设备 Deno
Deno 可以在 Mac、Linux 和 Windows 上工作。Deno 是一个独自的可实行文件,它没有额外的依托。你可以经过以下办法来设备它:
-
运用 Shell(Mac 和] : V Linux):
$ curl -fsSL https://deno.3 o ? F mland/x/install/install.sh |p x ! k R C . sh
-
运用 PowerShell(Windows)/ Y W T V:
iwr https://deno.land/x/install/install.ps1 -useW ~ 3 + A e 8b | iex
-
运用 Scoop (Windows):
scoop install deno
-
运用 Chocolatey (Windows):
choco install deno
-
运用 Homebv O p J c v Y trew (Mac):
brew install deno
-
运用 Cargo (Windows,Mac,Linux):
cargo install deno
Deno 也可以手动设备,只需从 github.com/denoland V | M p/de… 下载一个 zip 文件。它仅包含一个独自的可实行文件。在 Mac 和 Linux 上,你需求为它设置实行权限。当你成功设备之后,可以通h c e过实行 deno --version
指令来查看已设备的 Dek R x : 8 . 1no 版别:
$ deno --version
d$ u E M A B U ^ Yeno 1.1.2
v8 8.5.216
typescript 3.9.2
2.1 deno_ins1 M K c u etall
在设备过程中,假设遇到问题的话,我们可以试试 「justjavac(迷渡)」 大神供应G U o B的= f O 设备脚本 —— 「deno_install」。该脚本经过单行指令将 Deno 设备到P 0 ! e { k 系统| x 6 # V m n Z 7中(国内加速)。
2.1.1 设备最新版
运用 Sh^ a Qell:
$ curl -fsSL https://x.deno.js.cn/install.sh | sh
运用 PowerShell:
$ iwr https://x.deno.js.c] ! = m $ u zn/instT p J = % B Y 0all.ps1 -useb -outf install.ps1; .install.ps1
# iwr https:/9 B b 9 : I ) c/x.deno.js.cn/install.ps1 -useb | iex
2.1.2 设备某个特定版别
运用 Shell:
$ curl) w 8 u 2 P # ; -f M V D ZfsSL https! ( ] 3 g://x.deno.js.cn/install.sh | sh -s v0.41.0
运用 PowerShell:
$ iwr https:U U - z//x.deno.js.cn/install.ps1 -useb -outf insta @ s M Y F h ^ll.ps1; .install.ps1 v0.41.0
❝
更多具体的信息可以阅读 x.deno.js.cn 站点。
❞
2.2 deno-cli
deno-cli 指令行界面供应了一组y G o F K R $ b O集成功用,^ 8 – Y c让你可以沉浸在 Deno 的专有开发环境中。以下是 Deno 1.1.2 版别支撑的全部子指令:
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
ca L = l L & N 0cJ R Y n %he Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source9 ` V 8 files
help Prints this message or the help of the given subcommT W - f s ] 9 C rand(s)
info Show info about cache or info related to source file
install Install script as an executable
lint Lint source files
repl Read Eval( 1 T Print Loop
run Run a program given a filename or url to the module. Use '-' as a filename
to read from stdin.
test Run tests
types Print runtime TypeScript declarations
upgrade UpgZ C 5 s lra* E [ I Z 6 $ Kde deno executable to given version
2v O d Y.3 REPL
在指令中输入 deno 指令,你就会发起一个 「REPL(Read-Execute-Print-Loop)」:
$ deno
Deno 1.1.2
ex. t J Yit using ctrl+d or close()
> 0.1 + 0.2
0.30000000000000004
> const name =E / & _ d Y d "阿宝哥";7 6 O Q 8 A 6 4 j
undefined
> console.log(name);
阿宝哥
undefined
❝
“读取-求值-输出”循环(英语:Read-m C HEval-Print Loop,简称 REPL),也被称做交互式顶层构件(英语:interactive tod R a e lplevel),是一个简略的,交互式的编程环境。这个词常常用于指代一个 Lisp 的交互式开发环境,也能指代指令行的方式。
❞
2.4 VSCode Deno extension
信赖许多小y ; r _伙伴都在运用 VSCode IDE 进行 Web 开发,关于 Deno 的开发者来说,必定不能错失 Deno 官方开发的 Visual Studio Code Deno extej l S G 0 % Ansion 扩展。
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. T T [‘ instead0 5 . q g N.
❞
Deno 容许从 URL 中导入模块,但是 TypeScript 并不支撑从 URL 中导入模块。
❝
ts(2307): CanI o J ]not find module ‘https://deno.land/x/std/log/? # o y z S N `mod’.
❞
2.4.2 已设备 Deno extension
Denn Q } E w d Y 1o 将远程导入(imports)缓存在 $DENO_DIR
环境变量指定的特别9 s Y 4 [ {目录中。假设未指定 $DENO_DIR
,则默许为系统的缓存目录。
该插件可以将远程导入(remote imports)解析为本地途径。
(本章节图片来历:htJ n o Y itps://marketplace.visualstu j z ? j s Wdio.c# L G q D 4 Zom/items?itemNamew k q = ~ z [ n=denoland.vscode-deno)
❝
了解 VSCode Deno extension 更多的具体信息,可以阅读 「justjavac(迷渡M 0 / /)」 大佬 我为 VS Code 开发了一个 Deno 插件 这篇文章。
❞
三、Deno 初领会
3.1 Welcome 示例
信赖一些读者设备完 Deno 现已刻不容缓了,现在我们立马来领会一下 Deno 运用程序。首要翻开u z * m ~你了解R N k o o q I p的指令行,然后在指令行输入以下指令:
$ deno run https://denou b ( 2.lane E dd/std/examples/E 3 f ] h E ,welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https:/y m 3 4 q / G/deno.land/std/examples/welcome.ts
Welcome to Denz R )o
经过调查以上输出,我们可以知道当工作 deno run https://deno.land/std/examples/welcome.ts
指令之后,Deno 会先从 https:/c 5 y S H 9 , (/deno.land/std/examples/welcome.ts
URL 地址下载 wel& = g y v !come.ts
文件,该文件的内容是:
console.log("Welcome to Deno ");
当文件下载成功后,Deno 会对 welcome.ts
文件进行编译,即编译成 welco@ c ? S 2 N % Bme.ts.js
文件,然后再经过 V8 引擎来实行编译生成的 JavaScript 文件。需求留心的是,假设你在指令行从头工作上述指令,则会实行缓存中已生成的文件,并不会再次从网上下载| O a X 5 9 j [ , weli : b Scome.ts
文件。
$ deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno
那怎样证明再次实行上述指令时, Deno 会优先实行缓存中编译生成的 JavaScript 文件呢?这儿我们要先介绍一下 deno info
指令,M u S + B 6该指令用于显现有关缓存或源文件相关的信息:s a & e l ;
$ deno info
DENO_DIR location: "/Users/fer/Library/Caches/denoT Y . u #"
Remote modules cache: "/Users/fer/Library/Caches/deno/d3 c ? 5eps"
TypeScript compiler cache: "/Users/fer/Library/Caches/deno/gen"
在上述的输出信息+ D 0 ;中,% h 8 l # _ ( F Y我们看到了 「Tyh – G R A j m /peScript compiler cache」 这行记载,很明显这是 TypeScript 编译器缓存的目录,进入^ 9 V + d . # b ;该目录后,通Z N K ! o过一层层的查找,我们终究在 examples
目录下找到了 w6 h ] w ^ ]elcoh ^ H - hme.tg C *s.js
文件:
➜ examples ls
welcome.ts.buildinfo welcome.ts.jsB _ I u : { 7 r g.map
welcome.ts.js welcome.ts.meta} { z c : ~ 4 k
翻开目录中 welcome.ts.js
文6 v % S h件,我们可以看到以下内容:
"use strict";
console.log("Welcome to Dh . e b b aeno ");
//#sourceMappingURL=data:application/json;base64,eyJ2Z...
下面我们来修正该文件,在文件中添加一行输出信息 console.log("Hello Semlinker, from Cache");
,具体如下:
"use strict";
console.log("Hell/ + Q & { ~ 8o Semlinker, from Cache");
console.log("Welcome to Deno ");q 3 x ] I e o .
//#sourceMappingURL=data:applicatil z @ d S oon/json;base64,eyJ2Z...
接着我们在指令行中从头实行以下指令:
$ deno run https://deno.land/std/exL . z 9amples/welcome.ts
Hello SemlinkG ` ^er, from CacheV e i
Welcome to Deno
那么现在问题又来了,怎5 R | v g 4么强制改写缓存,即从头编译 TypeScript 代码呢o _ , 8?针对Z V D Z @这个问题,在工作 denV @ h oo run
指令时,我们需求添加 --reload
标志,来奉告 Deno 需求从头改~ i p 2 # A写指定文件:
$ deno run --reload https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https://deno.lanH 5 H Z = * 9 Ad/std/examples/welcome.ts
Welcome to Deno
除了 --reload
标志之外,Deno run 指令还支撑许多其他的标志,感爱好的读者可以工作 deno run --help
指令来查看更多的信息。
3.2 TCP Echo Se? w _ f 2 y K hrver
前面我们现已介绍了怎z , – 9 v么工作官方的 「we n 4 0 _ {lcome」 示例,下面我们来介绍怎样运用 Deno 创建一个d ) Y | C # f P简略的 TCP echo 服务器Z W w d $ E % Q 。首要我们创建一个 「learn-deno」 项目,3 / C U T Q G然后在该项目下新建一个D 9 R 「quickstart」 目录,接着新建一个 echo_server.ts
文件并输入以下代码:
const listener = Deno.listen({ port: 8080 });
console.log("listening on 0.0.0.0:8080");
for await (const conn of listener) {
Deno.copy(conn, conn);
}
❝
for await…o ? ;of 句子会在异步或许同步可迭代方针上创建一个迭代循环,包含 String,Array,Array-like 方针(比L o m d ) ] q $如 arguments 或许 NodeList),TypedArray,Map, Se u 8 e I Wt 和自定义的异步或许同步可迭代方针。
for await…of 的语法如下:8 D k G S % T
for await (variable of iterable) { statN N ] 3ement }
❞
输入完以上代码之后,信赖许多读者会跟我相O W ^ h d – S同,直接在指令行工作以下指令:
➜ quickstar6 S u @t deno run ./echo_server.t8 h gs
Compile file:///Users/fer/LearnProjects/learn-deno/quickstart/ecb ~ ? + . V ( ^ fho_serveE U 7 % V (r.ts
error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag
at unwrapResponse (9 E f d D }$deno$/o = z = 1 4 L 7 Ops/dispatch_json.ts:43:11)
at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
at Obj) 8 | n 2ect.listen ($deno$/ops/net.ts:51:10)
at Object.listen ($deno$/net.ts:152:22)
at file:///Users/fer/LearnProjects/learn-deno/quickstart/echo_server.tg $ 7 j C Ts:1:23
很明显是权限差错,从差错) H R 4 . 1 A 9信息中,Deno 奉告我们需求设置 --allow-net
标志,以容许网络访问。为什么i ( ? * ` G n P 4会这样呢?这是由于 Deno 是一个 JavaScript/TypeScript 的工作时,默许运用安全环境实行代码。下面我们添加 --allow-net
标志,然后再次工作 echo_server.ts
文件:
➜ quickstart deno run --allow-net ./echo_server.ts
listening on8 k @ 8 0.0.0.0:8080
当服务器成功工作之后,我们运用 nc
指令来检验一下服Y S M P务器的功用:
➜ ~ nc locv , % p J 1 Jalhost 8080
hell semlinker
hell semlinker
介绍完怎样运用 Deno 创建一个简略的 TCP echo 服务器,我们再来介绍_ L A一下怎样运用 Deno 创建g J O 9 i Z 1 m %一个简略的~ 6 $ 3 0 HTTP 服务器I : W。
3.3 HTTP Server
与 TCP Server 相同,在 「quickstart」 目录下,我们新建一个 http_server.ts
文件并输入以下内容V r ! r c K k:
import { serve } from "httpsz D @ ( - & /://deno.land/std@v0.50.0/http/serverf { W 0 G C ` | O.ts";
const PORT = 8080;
const s = serve({ port: PORT });
console.log(` ListT t 7 = r )ening on <http://localhost>:${PORT}/`);
for await (const reqO 8 - A of s) {
req.respond({ body: "Hello Semlinker\n" });
}
❝
友谊提示:在实践开发过程中,你可以从 ht9 M tps:U I s q ) l//deno.land/std 地址获取所需的标准库版别。示例中我们显式指定了版别,当然你也可以不指定版别,比方这样:https:/d ) L ~ b i P/deno.land/std/httG 2 6 &p/server.ts 。
❞
在Z 3 ; ~ m B上述代码中,我们导入了 DeP 7 T N 4 d e =no 标准库 http 模块中 serve 函数,然后运用该函数快速创建 HTTP 服务器,该函数的定义如下:
// https://github.com/denoland/deno/blob/master/stF j f 4 bd/http/server.ts
export function serve(addr: string | HTTPOptions): Server {
if (typeof addr === "string") {
const [hostname, portn } [ w 7 D] = addr.split(":");
addr = { hostname, port: Nu- : D +mber(port) };
}
c_ Q { H Monst listener = Deno.listeB F : ? Bn(addr);
return new Server(listener);
}
serve 函数接纳一个参数,其类型是 string | HTTPOptions
,其间 HTTPOpK N h f ] | Y I {tions 接口的定义如下:
/** Options fo# D z - b l Ir creating an HTTP server. */
expoi ; . j s ) brt type HTTPOptio[ [ Y h { x Gns = Omit<DO 4 m ? N 3 . !eno.ListenOptions, "transport">;
export interface ListeS 1 @ q ,nOptions {
/** The port to listen on. */
port: number;
/** A litero ^ 9 3 v ?al IP address or host name! 2 N that can be resolved to an IP address.
* If not specified, defaults to `0.0.0.0`. */
ho5 ] 1stname?: string;
}
当输x ( h U入的参数类型是字符串时,serve 函数会运用 :
冒号对字符串进行切开,获取 hostname
和 port
,然后包装成方针赋值给 addr 参数,接着运用 addr 参数继续调用 listen
函数进一步创建 listener
方针,终究调用 new Server(listener)
创建 HTTP 服务器。
创建完 HTTP 服务器,我们u 7 z d来发起该服务器,翻开? Y 5指令y a M } o行输入以下指令:
➜ quickstart deno run --allow-net ./http_server.ts
Compile fil+ W @ %e:///Users/fer/LearnProjects/learn-deno/quickstart/http_server.ts
Listening on <http://localhost>:8080/
接着翻开阅读器,在地址栏上输入 http://localho$ X s #st:8080/ 地址,之后在其时页J B A F _ n *面中会看到以下内容:
Hello Semlinkern
3.4 Cat 指令
介绍完怎样运用 Deno 建立一个 HTTP 服务器,接下来我们再来介绍怎样运用 Deno 开发一个z 6 E % ^简2 & ~ U F M 0略的 cat
指令。在 Linux 系统中,cat
指令用于联接文件m 5 9 } e N #并打印到标准输出设备上。. @ 9 u x v { ) 现在咱, P 6 . $ [们在 「quickstart」 目录下,新建一个 cat.ts
文件并输入以下内容:
for (let i = 0; i < Deno.args.length; i++) {
let filename = Deno.args[i];
let file = await Deno.open(filename);
await Deno.copy(file, Deno.stdout);
fh : m 2 , X 7 nile.close();
}
在以上代码中,我们运用了 Deno 命名空间下的 3 个 API,它们的作用如下:
-
Deno.args
:获取w + s H ` ( U 9脚本接纳的参数; -
Deno.open
:X $ 5 Z = 3 a用于翻开文件,回来一个 Promise 方针,r[ u 0 m x G h zesolve 后回来一个 Deno.File 方针; -
Deno.copy
:用于实行拷贝操作,结束从V a $ W ; 6 u b源到方针的拷贝。当遇到 EOF 或产生差错时,会中止拷贝操作。调用该办法后,也会回来一个 Promise 方针,rs ^ f I nesolv& T ke 后会回来已拷贝的字节数。
由于 Deno 是一个 JavaScript/TypeScr@ _ I ( a t U [ipt 的工作时,默许运用安全环境实行代码。因而在工作 cat.ts
脚本时,我们要设置 --allow-read
标志 ,已容许文件系统读访问。即具体的脚本如下所示:
➜ quickstart deno run --allow-read cat.ts echo_server.ts
以上指令成功工作后,控制台会输出以下作用:
const listener = Deno.listen({ port: 8080 });
console.log("listening on 0.0.0.0:8080");
for await (const coE ^ p z P L G nnn of listener) {
Deno.copy(conn, conn);
}
快速领会完 Deno,要进行实践项目开发,我们还得了解一下怎样调试 Deno 运用程序,所以下面我们将介绍怎样运用 Chrome Devtools 和 VSCode 调试 Deno 运用程序。
四、调试 Deno
Deno 支撑 V8 Inspector Protocol。运用 Chrome Dev9 c X Q ntools 或其他 Q a m支撑该协议的客户端(比方 VSCode)可以调试 Deno 程序。要启用调试功用,用 --inspect
或 --inspect-brk
选项工作 Deno,对应的D l M i p 2 X |选项描绘如下:
--inspect=<HOSTy ? {:PORT>
activate inspector on host:port (default: 127.0.0.1:9229)
--inspect-brk6 / { % - $ 6=<HOST:PORT>8 ! y M 8 _;
activate inspector on host:port and break at start of user script
--inspect
选项容许在v J v J A 4 d 9任何时间点联接调试器,而{ L S & ( 0 --inspect-brk
选项会等候调试器联接,在榜首行代码处暂停实行。
4.1 Chrome Devtools
让我们用 Chrome 开发者东西来调试一个简略的程序,我们将C * k # v E k 4运用来自 std
的 file_server.ts,这是一个简略的静态文件服务。
运用m M ] – l x --inspect-brk
选项,在榜首行代码处暂停实行。
$ deno run --i? z q n / e K Qnspect-brk --allow-read --allow-net https://deno[ m 2.land/std@v0.50.0/http/file_servl v W m 5 % fer.ts
Debugger listening on ws:Z v Y o F A i f p//| U K X h 2127.0.0.1:9229/ws/1e82c406-85a9-k F 3 ` Z u . e 844ab-I F K ( E W R R86b6-7341583480b1
Download https://deno.landm D m ) p y c/std@v0.50.0/http/file_serve+ k s w G Hr.ts
Compile https://M % h Gdeno.land/std@v0.50.[ 3 ! z0/http/file_server.ts
...
翻开 chrome://inspect
,点击 Target 周围的 Inspect
。
❝
进一步了解更具体的调试阐明,可# ] `访问 htQ 6 Ntps://deno.land/manual/tools/debugger U| ! 1 ; P b +RL 地址。
❞
4.2 VSCodef O G
Deno 可以在 VSCode 中调试。插件的官方支撑正在开发中 https://github.com/denoland/vscode_deno/issues/12,当然我们也可以经过手动供应 launch.jsoR V 1 F q { Qn
装备,来联接调试器:
{
"version": "0.2.0",
"configurations": [
{
"name": "Deno",
"type": "node",
"request": "launch",
"cwd": "${workx | {spaceFolder}",
"runtimeExZ o U ` M r , & oecutabla ? ;e? 6 1": "deno",
"runtimeArgs": ["run", "--inspect-brk", "-0 ` gA", "<entry_point>"],
"port": 9229
}
]
}
「留心」:将 <entry_poin[ y S E 0 b Gt>
替换为实践的脚本名称。
下面让我们来检验一下调试本地源文件,创建 server.ts
:
import { serve } from "https://deno.land/std@v0.50.0/httR D 0 b lp/seH k 8 c J 7 lrver.ts";
const s = serve({ port: 8000 });
console.log("http://lof Z { _calhost:8000/");
for await (const req oI * u [ R } Ef s) {
req.respond({ body: "Hello Worldn" });
}
将 <entry_point>
改为 server.ts
,然后工作。
(图片来历:https://deno.land/manual/tools/debugger)
(图片来历:https://deno.land/manual/tools/debugger)
五、Deno Web API
Deno 还支撑 W3C 标准标准,因而像 fetch
、setTimeout
、Blob
和 Worker
等 AN v _ $ Q B ^PI 都可以被直接运用。现在 Deno 已结束了以下 Web APIs:
-
Blob:用于标明二进制数据; -
Console:用于输出日志信息; -
CustomEvent,EventTarget 和 EventListener:用于处理 DOM 工作,需求留心的是,由于 Deno 中没有 DOM 层次结构,因而没有用于工作冒泡/捕获的树; -
fetch, Request, Response, BodyL z H G p P Y 和 Headers:现代依据 Promise 的 HTTP 央求 API; -
FormData:用于处理 multipart/form-data
表单数据; -
Performance: 高精度获取其时时间; -
setU 4 ( 7Timeout, setInterval, clearTimeout 和 clearInterval:处理和调度守时任务; -
Stream:用于创建、组合和运用数据流的 Stream Ah q O S O r * T gPI; -
URL 和 URLSearchParams: 用于结构和解析 URLs; -
Worker:在独自的线程中实行其他代码,需求留心的是,不支撑 Blob URLs,且无法转让方针A S ^全部权,传递的数据运用 JSON 序列化,而不是结构化克隆。
出于篇幅考虑考虑,阿宝哥不方案介绍上面全部 Web APIs,只方案简略介绍一下 Blob API 和 Worker API。* j A % n f P
5.1 Blob API
Blob(Binary Large Object)标明二进制类型的大方针。在数据库处理系统中,将二进制数据存储为一个g 1 ) y j t A =单一S U k 3 P个其他调集。Blob 通常是s x / # A x P j !影像、动静或多媒体文件。「在 JavaScript 中 Blob 类型的方针标明不可变的类似文件方针的原始W 1 ^ G j 3 p I q数据。」
Blob
由一个可选的字符串 type
(通常是 MIME 类% | n型)和 blobParts
组成:
❝
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,是设定某种扩展名的文件用一种运用程序x P a .来翻开的办法类型,当该扩展名文件D 8 s被访问的时分,阅读器会主w X 7 z & G D 8 动运用指定运用程序& w H 5 w Z , L 8来翻开。多用于指定一些客户端自定义的文件名,以及一些媒体文件翻开办法。R O 0
常见的 MIME 类型有:超文本符号言语文本 .html text/htmN p y | * ; nl、PNG图画 .png im) g s Q X = 9 Mage/png、一般文本 .txt text/plain 等。
❞
5.1.1 结构函数
Blob 结构函数的语法为:
var aBlob = new Blob(blobParts, options);
相关的参数阐明如下:
-
blobParts:它是一个由 ArrayBuffe` n 0 ) j A { v {r,As & # 3 o !rrayBufferView,Blob,DOMString 等方针构成的数组。DOMStrings 会被编码为 UTF-8。 -
options:一个可选的方针,包含以下两个特色: -
typ7 s P p o # S {e —— 默许值为 ""
,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。 -
endings —— 默许值为 "transparent"
,用于指定包含行结束符n
的字符串怎样被写入。 它是以Z W w %下两个值中的一个:"native"
,代表行结束符会被~ w 2 y t更改为合适宿主操作系统文件4 / x Z i系统的换行符,或许"transparent"
,代表会坚持 blob 中保存的结束符不变。
-
5.1.2 特色
前面我们现已知道 Blob 方针包含两个特色:
-
size(只读):标明 Blob
方针中所包含数据的大d ? = z 0 9 H小(以字节为单位)。 -
type(只读):一个字符串,标明该 Blob
方针所包含数据的 MIME 类型。假设类型不知道,则该值为空字符串。
5.1.3 办法
-
slice([start[, end[, cons ? 6 ? t v R : :tentType]]]):回来一个g t 6 A新的 Blob 方针,包含了源 Blob 方针中指定范围内的数据。 -
stream():回来一个能读取 blob 内容的 ReadableStream
。 -
text():回来一个 Promise 方针且包含 blob 全部内容的 UTF-8 格式的 USVString
。 ~ , p 4 -
arrayBufferZ & + Q()* 8 : 5 =:回来一个 Promise 方针且包含 blob 全部内N M b V容的二进制格式的 ArrayBuffer
。
这儿我们需求留心的是,「Blob
方针是不可改动的」。我们不能直接在一个 Blob 中更改数据,但是我们可以对一个 Blob 进行切割,从其间创建新的 Blob 方针,将它们混合到一个新的 Blob 中。这种# 4 s | E行为类似于 JavaScript 字符串:我们无法更改字符串中的字符,但可以创建新的更正后的字符串。
5.1.4 运用示例
let myBlobParts = ["<html><h2>Hello Semlinker</h2></htmI % 3 ` S + jl&g/ 7 H G ; _ j - Vt;"];
let myBlob = new Blob(myBlobParts, {
type: "text/9 D . { O z C [html",
ending: d T I"transparent",
});
console.log(myBlob.size + " bytesj E u D b ( f size");
console.log(myBlob.type + " is the type");
以上代码运用 deno run dy k Seno-blob.ts
指令工作后,指令行会输出以下D & L b w x作用:
37 bytes size
text/html is the type
5.2 Worker API
Web WorkU Ver 是 HTML5 标准的一部分,这一规k X ; 0范定义了一套 API,它容许一段 JavaScript 程序工作在主线程之外的别的一个线程中。Web Worker 的作用,就r : _ 3 I + +是为 JavaScrN | 7 4ipt 创造多线程环境,容许主线程创建 Worker 线程,将一些任务分配给后者工作。
在主线程工作的一起,Worker 线程在后台工作,两者Y H 5 m互不搅扰。比及 Worker 线程结束计算任务,再把作用回来给主线程。这样的好处是,可以在独立线程中处理一些计算密集型或高延迟的任务,从而容许主线程(通常是 UI 线程)不会因而被阻塞或拖慢。
(k 0 O d图片来历:https://viblo.asia/p/simple-web-workers-workflow-with-wY H _ Iebpack-3P0lPkobZox)
Worker() 结构函数创建一个 Worl 5 E oker 方针,该方针实行指定的URL脚本。这个脚本有必要遵循同源战略 。假设违背同源战略,则会抛出一个 SECURITY_ERR 类型的 DOMException。
5.2.1= 8 e Worker 结构函数
Worker 结构函数的语法为:
const myWorker = new Worker(aURL! ~ h, options);
相关的参数阐! b 2 n明如下:
-
aURL:是一个 DOMString 标明 worker 将实行的脚本的 URL; 1 6 L H d b。它有必要遵循同m Z 4 { d v ^ W源战略。 -
options(可选):包含可在创建方针实例– b G f ]时设置w + # ^的选项特色的方针。可用特色如下: -
type:用以指定 Worker 类型的 DOMString 值. 该值可以是 classix i & l hc 或 module。假设未指定,将运z ) : I t & m用默许值 classic。 -
credentials:用以指定 wo6 T a P X trker 凭证的 DOMString 值。该值可以是 omit,same-origin 或 include。假设未指定,或许 type 是 classic,将运用默许值 omit (不要求凭证)。 -
name:在 DedicatedWorkerGlobalScope 的情况下,用来Z v R N X f {标明 Worker 的 scope 的一个 DOMStrZ o Fing 值,主要用于调试目的。
-
需求留心的是,在创建 Web Worker 的时分,可能会出现以下失常:
-
当 do Q t | ( d $cument 不被容许发起 worker 的B 4 p Z *时分,将抛出一个 Securityj w O # ` 3 m L OError 失常。比方:假设供应的 aURL 有语法差错,或许与同源战略相冲突(跨域访问)。 -
假设 worker 的 MIME 类型不正确,将抛出p A 2 j i E一个 NetworkEr[ n ; # k u Y e 7ror 失常。worker 的 MIME 类型有必要是 text/javascrips Z - T Zt
。 -
假设 aURL 无法被解析(格式差错),将抛出一个 SyntaxError 失常。
5.1.2 运用示例
「main.ts」
const worke# ` 4 f K 1 ; wr = new Worker(new URL("worker.ts", import.meta.url).href, {
type: "module",
});
worker.onmessage = (e: Ms { S B I 1 @ UessageEvenm d I g O X | Dt) =>s q N . i ! [; {
console.log(`Main: Received msg from deno wou s p ; Grker - ${e.data}`);
};
worker.postMessage("Hello Deno");
「worker.ts」
self.onmessage = (e: MessageEvent) => {
console.loI Z T L | Xg(`Worker: Received from main - ${ew d w.data}`);
self.postMessage("Hello Semlinker");
};
以上代码运用 deno run& p h - --allow-read main.G X . i 2 y !ts
指令工作后,指令行会输出以下作用:
Worker: Received from main - Hello Deno
Main: Received msg from deno worker - Hello Semlinker
六、Deno Web 开发
信赖接a 1 6 k z k * 1 C触过 Node.js 的读者对 Express、Hapi、Koa 这些 Web 运用开发结构都不会陌生,在 Deno 途径中假设你也想做 Web 运用开发,能R @ K H s够考虑直接运用以下现成的结构:
-
abc:A better Deno framework to create8 M # L m u e web application。 -
deno-drash:A REST microframework for Deno wG ! O C X 8ith zero dependencies。 -
deno-express:Node Express way for Deno。 -
oak:A middleware framework for Deno’b H } a U x W xs net server 。 -
pogo:Server framework for Deno。 -
servest:A progressive http server for Den Q . bno。
写作本文时,现在` x ? F V % g h f Star 数最高的项目是 Oak,下面我们来简略介绍一下 Oak:
❝
A middleware framework for Deno’s http server, incluw R 1 m d /ding a router middleware.
This mK a 1 n J r 7 iiddly ^ peware framework is inspired by Koa and middleware router inspired by koa-router.
❞
很显然 Oak 的的构思来自于 Koa,而路由中间件的构思来历于 koa-router 这个库。假设你以前运用过 Koa 的话,信赖你会很简单上手 Oak。不信的话,我们来看个示+ z C例:
import { Application } from "https://deno.land/G . ` ( _ t K c Zx/oak/mod.ts";
const app = new Application();
app.use((ctx) => {
ctx.response.body = "HelloL R j { Semlinker!";
});
aws N 0 F 0 Z m sait ap? t @ D q n Op8 q A P & S { s.listen({ port: 8000 });
以上示例关于每个 HTTP 央求,都会响应 「“Hello S{ @ : / d $ ~ V demlinker!”」。只需一个中间件是不是感觉太 easo d J #y 了,下面我们来看一个更复杂的示例(H a I i @运用多个中间件):
import { Application } from "https://deno.lo N J j R * C qand/x/oak/modP M ; ; ] = ; u.ts";
const app = new Application();
// Logger
app.use(async (ctx, next) => {
await next();
const rt = ctx.respo[ z u p Jnse.headers.get("X-Response-Time");
console.log(`${ctx.request.method} ${ctx.request.url}y E ( - ${rt}`);
});
// Timing
app.use(async (cX , ! H j z L M 0tx, next) =&P 6 ~ 8 D - C (gt; {
const start = Da( x Hte.now();
awaR d M 7 ] e 5 Jit next();
const ms = Date.now() - start;
ctx.response.hef 3 / 3 @ $ c ; ^aders.set("X-ResO 6 E : f D } sponse-Time", `${ms}ms`);
});
// Hello World!
app.use((ctx) => {
ctx.response1 j X $ 6 m 6 P 1.body = "Hello. 7 A World!";
});
await app.li? s Y 1 b Q 7 +sten({ port: 8000 });
为了更好地理解 Oak 中间件流程控制,我们来一起回想一下 Koa 大名鼎鼎的 “洋葱模型”:
从 “洋葱模型” 示例图中我们可以很明晰的看到「一个央求从外到里一层一层的经过中间件,响应时从里到外一层一层的经过中间件。」 上述代码运用 deno run --allow-net oak/oak-middlewares-demo.ts
成功工作后,我们翻开阅读器X H C t 7,然后访问 http://localhost:8000/ URL 地址,之后在指令行会输r L F U i 4 v T %出以下作用:
GET http://localhost:8000/ - 0ms
GET http://localhost:8000/favicon.ico - 0ms
这儿我们只是简略介绍了 Oak,假设对 Oak 怎样开发 REST API 感^ = k 爱好的话,可以阅读阿宝哥 了不得的 DenB Z Z l 4 X ; ,o 实战教程 这篇文章。
七、阿宝哥有话说
7.1 D1 c ) u ~eno 怎样运用第三方模块
截止Y $ 1 4 –现在(2020-06-30)3 L p停止,Deno 支撑的第三方库的数目为 「707」 。
(图片来历:https://deno.land/x)
下面我们以我们了解的 lodash
为例,来看一下怎样运用第三方模块。首要在查找框中输入 lodash
,对应的查找作用如下:
(图片来历:https://deno.l( + M t ( )and/x)
接着选择你想要设备的模块,这儿阿宝哥W _ _ v E F O选择 deno_lodash
这个模块,点击该列表项会进入该模块的详情页。然后你就可以依据模块的阐明文S 7 m档来设备运用模块了,以下是文档中该模块的运用示例:
import _ from "https://deno.land/x/G Z . 5 !deno_lodash/mod.ts";
console.log(_.dl / ^ / sefaults({ 'a': 1 }, { 'a': 3, 'b': 2 }));
// → { 'a': 1P D r + ; 7 7 R, 'b': 2 }
console.log(_.partition([1, 2, 3, 4], (n:number) => n % 2));
// →{ ` [ R + g $ [[1, 3], [2, 4]]
7.2 Deno 怎样一致处理项目依托
在 Deno 项目中可以运用一个 deps.ts
文件来一致处理全部依托,其他当地直接从 deps.ts
一致引进,例如 oak 项目的 deps.ts
如下所示:
// hp . , uttps://github.com/oakserver/oak/blob/main/deps.ts
export {& 5 | copyBytes, equal } from "https://deno.land/std@0.59.0/bytes/mod.ts";
export { S$ ` = 6 7 qha1 } from "https://deno.land/std@0.59.0/hash/sha1.ts";
export { HmacSha256 } from "https://deno.land/std@0.59.0/hash/sha256.ts";
// 已省掉部分代码
// 3rd party dependencies
export {
contentType,
extension,
lookup,
} from "https://deno.land/x/media_types@v2.3.8/mod.ts";
export {
compi! % J b d Q Jle,
parse as pathParsm q =e,
pX ! Y L B X I W +athToRegexp,
} from "https://ra^ w | t 0w.git/ C J k a A c (hubusercontent.com/pillarjs/path-to-regexp/v6.1.0/src/index.ts";
那么怎样查找这些模块呢?除了在前面提到的 Deno 官网 「第三方模块」 页面查找之外,你也可以在 「pika$ y 5 ` | S % ] t」 中寻觅指定的模块,假设查找出来的作用能直接运用,不会报错,标明该Q F ~ T T Q模块可以正常在 deno 中6 E ] } + p k运用。
7.3 Deno 怎样运用 npm 包
在 Denoi Z 0 o 中假设要运用 npm 包,可以运用 Deno 标准库中供应~ ! |的 createRequire
办法,具体运用办法如下:
import { createRequire } from "https://deno.land/std/node/module.ts";
const require = createRequire(import.meta.url);
// L| l noaF I ] w } ads native module polyfill.
const path = require("patz B + n T x Hh");
// Loads extensionless module.
const cjsModule = require(g j U } k 5 A Q F"./myw V )_mod");
// Visits node_modules.
const leftj = x J : vPad = require("left-pad");
除此之外,Deno 还可以凭仗 jspm.io 的才能来调用 npmu ) 5 C f 5 R w 1 的模块,感爱好的小伙伴可以阅读 Deno凭仗jspm运用npm 这篇文章。
7.4 怎n q 1 M j r X i么用一个代码库来维护一起支撑 Dx J _ 0 ~eno 和i V A k npm 的模块
尽管将模块移植到 Deno 非常简单,可H # v y G是你要维护两个代码库却很费事。所以假设你想只运用一个Z Z q & R E ? Y 5代码库来维护一起支撑 Deno 和 npm 的模块,这时你可以考} C a ? g虑运用 denoify 这个东西。
denoify 是一个构建东西,该构建东西将旨在以 node 或 weJ – 0b 为方针的 TypeScript 代码库作为输入,并将源文件的修正版别作为 Deno模块部署。d * J b [ B 8 `
(图片来历:htts p l ] 6 ; ? ) Ops://github.com/garronej/denoify)
以下是运用 denoify 开发的模块:
-
EVT -
run-exclusive
感爱好的小伙伴,可以自行了解一下上述的模块。别的,假设你也想要在项目中运用 denH k U y ~ 9 _oify ,那么可以参看这个库房,该库房J L A ! ~ # , ^会一步步教你怎样在项目中装备 denoify 。
八、总结
本文从七个方面下手,介绍了 DeY F 8 P v j C o Qno 入门相关的根底知识,期望对 Deno 初学者能有一些协助,当然有写得欠好的当地欢迎小伙伴们指出。Deno 现在还在高速地开展,标准库还未正式发布安稳的版别,写作本文时,最新版别是o A 3 5 . ` 6 「0.59.0」。比较成熟的 Node.js 社区,DeZ : ] } d s qno 社区还有很长一段路要走,感爱好的2 e : n } h F U –小伙伴们可以继续重视它。
阿宝哥是在 Deno 1.0.0 发布后才正式学习 Deno,现在也还在不断学习中。对阿宝哥个人来说,近期比较感爱好的是 Deno Web API,因而近期也花了蛮多时间学习 DenI O p } y t C d )o Web API 的结束。在学习过程中,B e ` a P B 5 |也遇到挺多问题的,这儿要感谢 「justjavac(迷渡大大)」 的耐性回答。+ ; % ; S #
能看到这f { g 4儿的小伙伴都是 “真爱”,最终感谢我们阅读本教程,欢迎对 Deno 感爱好的小伙伴跟阿宝哥一起交流w m :和学习 Deno。
九、参看资源
-
Deno 中文手册 -
Deno 怎样运用 npm 包? -
怎样点评 deno 方案把一些内部模块从p L u B ts 改回 js ? -
Github – oak -
the-deno-handbook -
deno-first-approach -
the-deno-handbook -
write-a-small-apy k & 9 } – Y y ^i-using-deno
创建了一个 「“全栈修仙之路交流群”」 的微信群,想加群的小伙伴,加我微信 “} w nsemlinker”,备注 「2」。阿里、京; g q n + W Z东、腾讯的大佬都在群里等你哟。
❞
本文运用 mdnice 排版