前言
自 Deno 1.0 发布以来,这几天关于它的公众号推文数不胜数,但大多都是介绍它和 node 的区别,以及带来的好处。却并没有说怎么玩,出于好奇的目的(没有女朋友陪逛街),打算研究一下。
如果你还不知道 Deno 是什么,那阮一峰老师的这篇文章值得一看,链接地址:http://www.ruanyifeng.com/blog/2020/01/deno-intro.html。说白了,它是 Node.js 的作者新搞的一个 Node.js 的替代品,究其原因,是他对 Node.js 有些不满意。不禁感叹,大神就是大神,Node.js 可以说是一个直接影响了前端领域,甚至让前端这个行业真正起飞的项目,说要来过就要来过。
抛去那些优化的东西不说,Deno 相对于 Node.js 而言,个人觉得有三个比较大的变更,也可以说是它们两者之间最本质的区别:
1、底层依赖的语言不同了,Node.js 的底层语言用的是C++,而 Deno 用的是 Rust;
2、Deno 具有安全控制,默认情况下脚本不具有读写权限。如果脚本未授权,就读写文件系统或网络,会报错。
必须使用参数,显式打开权限才可以;
对安全控制不太明白?我们都知道,Node.js 可以随便读写文件,发送网络请求,而 Deno 不行,必须要用户显示指定,这个的好处在于我们使用别人的代码时(比如:第三方插件),不被恶意攻击。
3、Deno 不再使用 npm 安装包的方式,彻底告别 require 命令,以及 node_modules 文件夹。
接下来,我们就来简单的玩玩 Deno。
**阅读提醒,本文所有代码片段里的第一行以磁盘路径开头的,类似C:\Users\Administrator>xxx,尖括号后面的内容为命令内容,为了和输出结果区分开来,特地中间空了一行。**
一、安装
命令行安装的方式多种多样,要区分电脑系统,你还不一定能安装成功。所以我们直接将下载安装文件的方式。
直接去 Deno 的github 官网下载编译好的可执行文件,下载地址:https://github.com/denoland/deno/releases。
1 2 |
Deno 1.0.0 exit using ctrl+d or close() |
不言而喻,它代表着我们的 Deno 执行文件是可用的,第一行输出的是版本,第二行是提醒你怎么退出这个执行文件。接着,我们就可以在里面写我们的 js 代码了,你可以先试着输入一个console.log(1) 试一下,也可以输入 close() 把它关闭。
二、配置环境变量
上面的执行文件已经没问题了,但我们却不能在 cmd 或者其他命令行工具里面用 Deno 的命令,解决这个问题很简单,我们只需给 Deno 配置好环境变量即可。配置方式,把你执行文件存放的目录添加到计算机系统变量的 path 里面(如果有不知道怎么添加环境变量的自己科普),以我的为例,我的存放目录是 D:\Program Files\deno,那我添加的环境变量就是 D:\Program Files\deno\。
添加好之后,重新打开命令行工具,执行 deno,如果你能看到跟上面一样的输出信息,就说明环境变量配置好了。接下来的内容是建立在这之上的,所以一定保证这里没问题。
三、认识 Deno
Deno 原生支持 TypeScript 语言,可以直接运行,不必显式转码。它的内部会根据文件后缀名判断,如果是.ts
后缀名,就先调用 TS 编译器,将其编译成 JavaScript;如果是.js
后缀名,就直接传入 V8 引擎运行。同时它可以直接执行线上文件,这是 node_modules 文件夹不复存在的关键。
打开我们的 cmd,试着执行以下命令:
1 |
deno run https://deno.land/std/examples/welcome.ts |
命令后面的 xxx.ts 是线上文件,所以请保证你在操作时是联网的,我们可以看到,打印出的信息如下:
1 2 3 4 5 6 |
C:\Users\Administrator>deno run 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.land/std/examples/welcome.ts Welcome to Deno |
从打印信息我们可以看出(第一行是执行命令),它是先下载文件,再编译文件,最后输出结果。也许你觉得这样每次都下载文件很麻烦,那我们再重新执行一次上面的命令:
1 2 3 |
C:\Users\Administrator>deno run https://deno.land/std/examples/welcome.ts Welcome to Deno |
我们发现,这次已经没有下载和编译的过程了,可想而知,那它肯定是对我们的编译文件进行了缓存,缓存在了哪里呢,我们执行以下命令看一下:
1 2 3 4 5 |
C:\Users\Administrator>deno info DENO_DIR location: "C:\\Users\\Administrator\\AppData\\Local\\deno" Remote modules cache: "C:\\Users\\Administrator\\AppData\\Local\\deno\\deps" TypeScript compiler cache: "C:\\Users\\Administrator\\AppData\\Local\\deno\\gen" |
我们可以看到输出了三个信息,分别是DENO_DIR location,Remote modules cache 和 TypeScript compiler cache。那最后一个肯定就是 ts 的缓存目录了,我们按着这个信息找,结果果然在 C:\Users\Administrator\AppData\Local\deno\gen\https\deno.land\std\examples 目录下找到了一个叫 welcome.ts.js 的文件,不难猜出,它就是在 welcome.ts 的后面加了后缀 .js。里面的内容如下:
1 2 3 4 |
"use strict"; console.log("Welcome to Deno"); //# sourceMappingURL=file:///C:/Users/Administrator/AppData/Local/deno/gen/https/deno.land/std/examples /welcome.ts.js.map |
我们试着修改一下里面的内容,在里面多加一句:console.log(“我是新添加的内容哦”);
1 2 3 4 |
C:\Users\Administrator>deno run https://deno.land/std/examples/welcome.ts Welcome to Deno 我是新添加的内容哦 |
除了缓存之外,我们通过上面的目录应该还发现一个问题,那就是缓存的目录是以执行文件的网址来创建的(以‘/’ 分割的多级目录),注意对比:
缓存目录:C:\Users\Administrator\AppData\Local\deno\gen\https\deno.land\std\examples
执行文件地址:deno run https://deno.land/std/examples/welcome.ts
还有一点,因为我执行 deno 命令时 cmd 窗口的地址是:C:\Users\Administrator>,所以我们执行 deno 命令时,它的相对目录就是C:\Users\Administrator\
为了验证猜想,我又去 C:\Users\Administrator\AppData\Local\deno\gen 目录下添加了一个叫 library.js 的文件,里面随便写点东西,然后执行如下命令,果然得到相关输出:
1 2 |
C:\Users\Administrator>deno run ./AppData/Local/deno/gen/library.js 我来自一个周末宅男的console命令 |
四、牛刀小试
缓存目录和执行文件的东西我们搞明白了,就来几个简单的功能玩玩吧。
小试第一刀:在 E:/deno 下创建一个 base 目录,新建一个 server.ts 文件,写入如下内容:
1 2 3 4 5 6 |
// 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); } |
执行命令 deno run server.ts,(注意执行环境是E:\deno\base>)
1 2 3 4 5 6 7 8 9 |
E:\deno\base> deno run ./echo_server.ts Compile file:///E:/deno/base/echo_server.ts error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11) at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10) at Object.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.ts:1:23 |
我们发现,报错了,错误信息也很明显,
PermissionDenied: network access to “0.0.0.0:8080”, run again with the –allow-net flag
就是说我们没有网络权限,需要制定 –allow-net 才行,这正是我们之前说了,Deno 有了安全机制。
重新执行:
1 2 3 4 |
E:\deno\base> deno run --allow-net ./echo_server.ts Compile file:///E:/deno/base/echo_server.ts listening on 0.0.0.0:8080 |
这时,已经正确执行了,说明我们的 server 建立成功了。
小试第二刀、再创建一个 http_server.ts 的文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 |
// 去远程下载相关依赖 import { serve } from "https://deno.land/std@v0.50.0/http/server.ts"; const PORT = 8080; const s = serve({ port: PORT }); console.log(` Listening on <http://localhost>:${PORT}/`); for await (const req of s) { req.respond({ body: "Hello Deno" }); } |
执行命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
E:\deno\base> deno run --allow-net ./http_server.ts Compile file:///E:/deno/base/http_server.ts Download https://deno.land/std@v0.50.0/http/server.ts Download https://deno.land/std@v0.50.0/encoding/utf8.ts Download https://deno.land/std@v0.50.0/io/bufio.ts Download https://deno.land/std@v0.50.0/testing/asserts.ts Download https://deno.land/std@v0.50.0/async/mod.ts Download https://deno.land/std@v0.50.0/http/_io.ts Download https://deno.land/std@v0.50.0/io/util.ts Download https://deno.land/std@v0.50.0/path/mod.ts Download https://deno.land/std@v0.50.0/path/win32.ts Download https://deno.land/std@v0.50.0/path/posix.ts Download https://deno.land/std@v0.50.0/path/common.ts Download https://deno.land/std@v0.50.0/path/separator.ts Download https://deno.land/std@v0.50.0/path/interface.ts Download https://deno.land/std@v0.50.0/path/glob.ts Download https://deno.land/std@v0.50.0/path/_constants.ts Download https://deno.land/std@v0.50.0/path/_util.ts Download https://deno.land/std@v0.50.0/fmt/colors.ts Download https://deno.land/std@v0.50.0/testing/diff.ts Download https://deno.land/std@v0.50.0/path/_globrex.ts Download https://deno.land/std@v0.50.0/async/deferred.ts Download https://deno.land/std@v0.50.0/async/delay.ts Download https://deno.land/std@v0.50.0/async/mux_async_iterator.ts Download https://deno.land/std@v0.50.0/textproto/mod.ts Download https://deno.land/std@v0.50.0/http/http_status.ts Download https://deno.land/std@v0.50.0/bytes/mod.ts Listening on <http://localhost>:8080/ |
我们可以看到,这次多了很多的下载命令,那是因为我们需要从远程获取 serve.ts,而 serve.ts 又正好依赖于上面那些模块。但就像我们之前说的缓存一样,一旦下载了,就会缓存,下次就不需要再下载了。
打开浏览器,访问localhost:8080,就会看到页面上出现了 Hello Deno 的字样。
小试第三刀、新建一个 cur.ts 文件,写入如下内容:
1 2 3 4 5 |
const url = Deno.args[0]; const res = await fetch(url); const body = new Uint8Array(await res.arrayBuffer()); await Deno.stdout.write(body); |
执行命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
E:\deno\base>deno run --allow-net=example.com https://deno.land/std/examples/curl.ts https://example.com Download https://deno.land/std/examples/curl.ts Warning Implicitly using master branch https://deno.land/std/examples/curl.ts Compile https://deno.land/std/examples/curl.ts <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> body { background-color: #f0f0f2; margin: 0; padding: 0; font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } div { width: 600px; margin: 5em auto; padding: 2em; background-color: #fdfdff; border-radius: 0.5em; box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02); } a:link, a:visited { color: #38488f; text-decoration: none; } @media (max-width: 700px) { div { margin: 0 auto; width: auto; } } </style> </head> <body> <div> <h1>Example Domain</h1> <p>This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.</p> <p><a href="https://www.iana.org/domains/example">More information...</a></p> </div> </body> </html> |
可以看到,上面的输出结果,html 部门跟我们打开 https://example.com 看到的一模一样,他其实就是把请求到的内容通过 buffer 的形式在控制台输出了而已。
小试第四刀、新建一个file.ts,内容如下:
1 2 3 4 5 6 |
const filenames = Deno.args; for (const filename of filenames) { const file = await Deno.open(filename); await Deno.copy(file, Deno.stdout); file.close(); } |
再新建一个 file 文件夹,里面新建一个 test.txt 的文件,随便写点文字,abcdefg,执行命令:
1 2 3 |
E:\deno\base>deno run --allow-read ./file.ts ./file/test.txt abcdefg |
可以看到,文件里的内容被读取到了控制台输出出来。
好了,由于现阶段 Deno 的参考资源有限,本篇文章就先聊到这里,后面有机会再补充,如果笔误,欢迎斧正。
本博客公众号:前端扫地生
发表评论