这几天假期,我学习了一下 Deno。它是 Node.js 的替代品。有了它,将来可能就不需要 Node.js 了。
这篇文章就是 Deno 的一个初步介绍,尝试回答为什么 Node.js 不能满足需要,以及 Deno 能够带给我们什么?
以下内容主要基于 Bert Belder 和 Ryan Dahl 的最新演讲。
0、
进入主题之前,先说一下 Deno 这个词怎么发音。
两种发音,"德诺"和"蒂诺",我都听到过。看起来,"蒂诺"这个发音应该更合适一些,因为 Deno 的标志是一只恐龙。恐龙(dinosaur)的英文缩写正是 dino。
1、
Deno 是 Ryan Dahl 在2017年创立的。
Ryan Dahl 也是 Node.js 的创始人,从2007年一直到2012年,他后来把 Node.js 移交给了其他开发者,不再过问了,转而研究人工智能。
他始终不是很喜欢 Python 语言,久而久之,就想搞一个 JavaScript 语言的人工智能开发框架。等到他再回过头捡起 Node.js,发现这个项目已经背离了他的初衷,有一些无法忽视的问题。
2、
首先,过去五六年,JavaScript 语言脱胎换骨,ES6 标准引入了大量新的语法特性。其中,影响最大的语法有两个:Promise 接口(以及 async 函数)和 ES 模块。
Node.js 对这两个新语法的支持,都不理想。由于历史原因,Node.js 必须支持回调函数(callback),导致异步接口会有 Promise 和回调函数两种写法;同时,Node.js 自己的模块格式 CommonJS 与 ES 模块不兼容,导致迟迟无法完全支持 ES 模块。
其次,Node.js 的模块管理工具 npm,逻辑越来越复杂;模块安装目录 npm_modules 极其庞杂,难以管理。Node.js 也几乎没有安全措施,用户只要下载了外部模块,就只好听任别人的代码在本地运行,进行各种读写操作。
再次,Node.js 的功能也不完整,导致外部工具层出不穷,让开发者疲劳不堪:webpack,babel,typescript、eslint、prettier......
3、
由于上面这些原因,Ryan Dahl 决定放弃 Node.js,从头写一个替代品,彻底解决这些问题。deno 这个名字就是来自 Node 的字母重新组合(Node = no + de),表示"拆除 Node.js"(de = destroy, no = Node.js)。
跟 Node.js 一样,Deno 也是一个服务器运行时,但是支持多种语言,可以直接运行 JavaScript、TypeScript 和 WebAssembly 程序。
它内置了 V8 引擎,用来解释 JavaScript。同时,也内置了 tsc 引擎,解释 TypeScript。它使用 Rust 语言开发,由于 Rust 原生支持 WebAssembly,所以它也能直接运行 WebAssembly。它的异步操作不使用 libuv 这个库,而是使用 Rust 语言的 Tokio 库,来实现事件循环(event loop)。
4、
你可能会问,为什么使用 Rust,而不是 C++(Node.js 的开发语言)?
主要原因是 Rust 提供了很多现成的模块,对 Deno 项目来说,可以节约很多开发时间。
5、
Deno 本身也是 Rust 的一个模块。如果你想在 Rust 里面使用 V8 引擎,就可以加载 Deno。它等于是一个 V8 的包装层,提供一些底层 API,让你跟 V8 引擎互动。
6、
Deno 只有一个可执行文件,所有操作都通过这个文件完成。它支持跨平台(Mac、Linux、Windows)。
7、
Deno 具有安全控制,默认情况下脚本不具有读写权限。如果脚本未授权,就读写文件系统或网络,会报错。
必须使用参数,显式打开权限才可以。
--allow-read
:打开读权限,可以指定可读的目录,比如--allow-read=/temp
。--allow-write
:打开写权限。--allow-net=google.com
:允许网络通信,可以指定可请求的域,比如--allow-net=google.com
。--allow-env
:允许读取环境变量。
8、
Deno 支持 Web API,尽量跟浏览器保持一致。
它提供 window 这个全局对象,同时支持 fetch、webCrypto、worker 等 Web 标准,也支持 onload、onunload、addEventListener 等事件操作函数。
此外,Deno 所有的异步操作,一律返回 Promise。
9、
Deno 只支持 ES 模块,跟浏览器的模块加载规则一致。没有 npm,没有 npm_modules 目录,没有require()
命令(即不支持 CommonJS 模块),也不需要package.json
文件。
所有模块通过 URL 加载,比如import { bar } from "https://foo.com/bar.ts"
(绝对 URL)或import { bar } from './foo/bar.ts'
(相对 URL)。因此,Deno 不需要一个中心化的模块储存系统,可以从任何地方加载模块。
但是,Deno 下载模块以后,依然会有一个总的目录,在本地缓存模块,因此可以离线使用。
10、
由于 Deno 只支持从 URL 加载模块,导致 Node.js 的模块加载写法都会失效。
import React from "react"; import { Box, Grid } from "@material-ui/core"; import { initializeApp } from "firebase/app";
上面的写法在 Deno 里面都是非法的。
Deno 的所有模块都要通过入口脚本加载,不能通过模块名加载,所以必须带有脚本后缀名。
11、
Deno 原生支持 TypeScript 语言,可以直接运行,不必显式转码。
它的内部会根据文件后缀名判断,如果是.ts
后缀名,就先调用 TS 编译器,将其编译成 JavaScript;如果是.js
后缀名,就直接传入 V8 引擎运行。
12、
Deno 内置了开发者需要的各种功能,不再需要外部工具。打包、格式清理、测试、安装、文档生成、linting、脚本编译成可执行文件等,都有专门命令。
执行deno -h
或deno help
,就可以显示 Deno 支持的子命令。
deno bundle
:将脚本和依赖打包deno eval
:执行代码deno fetch
:将依赖抓取到本地deno fmt
:代码的格式美化deno help
:等同于-h
参数deno info
:显示本地的依赖缓存deno install
:将脚本安装为可执行文件deno repl
:进入 REPL 环境deno run
:运行脚本deno test
:运行测试
13、
Deno 的安装可以参考官网首页,但是你可以直接去 GitHub 仓库的发布页,下载编译好的可执行文件(上图)。
下载 Deno 以后,查看一下版本。
$ deno --version deno 0.31.0 v8 8.1.108 typescript 3.7.2
命令行直接运行deno
,就会进入 REPL 环境。
$ deno > console.log(1,2,3) 1 2 3 undefined >
14、
下面,运行一个 TypeScript 的远程脚本,这是官网给出的例子。
$ deno run \ https://deno.land/std/examples/curl.ts \ https://example.com
上面例子中,Deno 执行远程脚本curl.ts
,用这个脚本去抓取网址example.com
。但是,运行后报错,表示没有网络通信的权限。
我们给予 Deno 网络通信的权限,就可以顺利执行。
$ deno run --allow-net \ https://deno.land/std/examples/curl.ts \ https://example.com
15、
现在,Deno 最新版本是 0.31。根据规划,1.0 应该会在今年上半年发布。
Deno 还处在密集开发中,功能不稳定,不建议用于生产环境。但是,它已经是一个可用的工具,大家可以多试用,熟悉它的用法。我相信,设计上的诸多优点,将会使它比 Node.js 更具优势。
(完)
foxDaxian 说:
照这么说,前端是不是要进军人工智能了...
2020年1月26日 20:15 | # | 引用
aoyama 说:
不错,看起来既轻便又强大。
2020年1月26日 20:31 | # | 引用
SimonAking 说:
支持从URL导入包, deno的生态 岂不是从一开始就很庞大...
2020年1月26日 20:37 | # | 引用
展翼骐骥 说:
TensorFlow本来就有js版本。其实PYTHON的运行效率跟node的差别是数量级级的。
2020年1月26日 21:03 | # | 引用
Ritchie 说:
deno可能会是未来的趋势之一,期待!
2020年1月26日 21:23 | # | 引用
xkloveme 说:
春节期间笔耕不辍,加油
2020年1月26日 21:45 | # | 引用
卜青云 说:
小白请教下怎么加速下载deno鸭...
2020年1月26日 22:25 | # | 引用
yuchen 说:
一定会取代 nodejs 的,因为在编程里方便高效是永远的追求,deno 是一种迭代。
2020年1月26日 23:54 | # | 引用
晨曦 说:
我对着npm就是一脚!对web开发人员更加友好了!
2020年1月27日 11:38 | # | 引用
Ryu 说:
runtime翻译为“runtime运行环境”会不会更好,运行时虽然也对,但是总有点莫名其妙的感觉
2020年1月27日 23:19 | # | 引用
yongq 说:
恐龍的發音是 /ˈdaɪnəsɔːr/
所以德諾更合適,
可以聽聽Ryan Dahl怎麽念的:
https://www.youtube.com/watch?v=z6JRlx5NC9E
2020年1月28日 07:35 | # | 引用
Logic 说:
不需要package.json,直接从url加载模块
不会更难管理么,到处都是,都不知道加载了哪些模块
2020年1月31日 10:54 | # | 引用
Hugh 说:
“不需要package.json,直接从url加载模块
不会更难管理么,到处都是,都不知道加载了哪些模块”
那也是开发人员自己引入的呀,本地也有保存的,一样的呀(你的意思是没有包管理审核)
我的一个flutter项目,里面好几个插件不更新,导致我都没法更新flutter最新版,证明有包管理也没用。
2020年2月 1日 01:09 | # | 引用
万里 说:
怎么我看到另一个开发者说Deno是使用Golang开发的?https://studygolang.com/articles/13101
2020年2月 4日 21:20 | # | 引用
Aloha 说:
Deno早期是Golang + TypeScript的,后来因为Golang和V8的GC问题,Ryan下了大工夫把golang统统换成没有GC的Rust了
2020年2月 7日 21:18 | # | 引用
mango 说:
好难过,nodejs还没有玩好,好好体验过他的魅力,现在deno又来插脚,????
2020年2月10日 16:43 | # | 引用
hank 说:
deno 是 no de交换前后位置得到的名字
2020年2月11日 22:28 | # | 引用
忧郁的风 说:
优点感觉挺不错的,但是不能用模块名导入感觉不太方便啊
不过nodejs里的回调确实打脑壳
2020年2月14日 14:48 | # | 引用
gaojiren 说:
看起来很棒哦,我非常看好这种优雅的使用方式,马上要出正式版了,花点功夫学习下!
2020年2月20日 13:35 | # | 引用
kelvin 说:
我现在手中有个项目,享用NODEJS来做, 需要调用系统注册的COM组件,网上找不到任何方法,这个到底设计到NODE哪一块,是否可行,要不然真的项目选型就浪费很多时间了
2020年2月20日 15:57 | # | 引用
Can 说:
还是 Common Lisp 比较好用
2020年2月25日 00:49 | # | 引用
春续 说:
依赖怎么解决?
2020年2月26日 12:40 | # | 引用
Kranite 说:
deno 为啥不是 define node
2020年3月 1日 19:45 | # | 引用
萌芽子 说:
看起来非常便利,支持!
2020年3月 5日 12:01 | # | 引用
吾仁别克 说:
我觉得很赞!期待deno V1.0。争当第一个吃螃蟹的。
2020年3月10日 16:15 | # | 引用
JoshDaone 说:
引用下manual.md里提到的deno设计哲学:
Philosophy
Deno aims to be a productive and secure scripting environment for the modern programmer.
Deno will always be distributed as a single executable. Given a URL to a Deno program, it is runnable with nothing more than the 10 megabyte zipped executable. Deno explicitly takes on the role of both runtime and package manager. It uses a standard browser-compatible protocol for loading modules: URLs.
Among other things, Deno is a great replacement for utility scripts that may have been historically written with bash or python.
2020年3月11日 00:53 | # | 引用
Astlvk 说:
期待早日实装,想用js尝试ai。
2020年3月12日 13:32 | # | 引用
ddd 说:
取代node还是需要一定的时间去积累
2020年3月17日 00:10 | # | 引用
Jser 说:
我正在學node,知道deno今年可能發布版本目前噴鼻血中
2020年3月18日 13:14 | # | 引用
Violet_ice紫冰 说:
并不是,传统npm包全都没法用的。必须要基于deno的包。或者是原生包。
2020年3月22日 23:10 | # | 引用
zz 说:
玩node那帮人都搞golang了,我是学golang还是学rust好呢哈哈
2020年3月25日 16:10 | # | 引用
唯愿饶安 说:
新技术的发展是必须的,前端产业的技术几年前就没有更新了,倒还挺期待这个技术,力争做吃螃蟹的人。
2020年3月26日 15:21 | # | 引用
chenplusplus 说:
确实,node_modules太复杂了,头疼
2020年3月26日 15:21 | # | 引用
Deno Master 说:
谷歌的Fuchsia OS支持的开发语言中包含Rust而不包含Golang,亲儿子都抛弃了,你说呢?
2020年3月27日 10:30 | # | 引用
许慧洁 说:
能够内置工具真的太方便了,最近学习webpack,babel感觉有些绕,相互耦合性很高。
2020年3月27日 22:38 | # | 引用
NauskiiFire 说:
不懂就问,意思是python效率高还是node效率高?
2020年3月29日 23:50 | # | 引用
superjpg 说:
就目前形势来看,npm是全球最大的包管理仓库没有之一,npm是基于node环境下运行的,所以,取代node并不是很容易,当然就deno的开发方向,个人感觉是对node代码的整合和规范,当然也有各自的优势,但是可以确定的是,很长一段时间都要继续使用node。
2020年3月31日 18:09 | # | 引用
可靠小弟 说:
deno是ry最初的想法回归,本来node就是期待用来简化后端的,没想到玩成了前端的生态。deno前景鸿远,让JavaScript在后端应用层打下了更坚固的位置。如果能出一款一统各种端的语言,就像秦始皇统一汉语一样[滑稽],无疑成为IT业界的历史时刻啊,那时候解放程序员重复学习的脑袋,注重业务功能实践,将会步入软件鼎盛之时,到处都有软件,到处都有智能,打个车只需讲一句话就直接传上云招来车,连路灯都联网,我希望这门语言会是ECMAScript[滑稽]。
2020年4月 2日 00:14 | # | 引用
程序汪 说:
需要实际去做一个对比来验证是否拥有效率提升,但是习惯上肯可能目前还不太适应吧。期待吧!
2020年4月 3日 14:36 | # | 引用
低调的帅哥 说:
活到老学到老啊
2020年4月 7日 15:14 | # | 引用
啦啦啦 说:
node才学到一半,然后说不用了,要学习deno啦
2020年4月 8日 15:42 | # | 引用
996 说:
deno 的文档终于出来了
https://doc.deno.land/https/github.com/denoland/deno/releases/latest/download/lib.deno.d.ts
2020年4月 9日 20:08 | # | 引用
Aero 说:
说起来,我最近刚刚把前端的东西差不多都笼统的搂了一遍,正在感慨,“杂乱无章,真特么恶心”。(但还是忍着恶心学了)
他现在说重写,就搞得我一面我非常高兴,一面我又非常愤怒,惋惜这么久的学习成果。。。。。
2020年4月 9日 21:56 | # | 引用
balefulJS 说:
deno 快要发布1.0 正式版本了,期待前辈的新作布道
2020年4月14日 15:28 | # | 引用
裤裆三重奏 说:
「此外,Deno 所有的异步操作,一律返回 Promise」
关于这个,如果是 node 中的多次回调该如何解决呢?
比如:读取文件,fs.createReadStream,需要将获取到的数据通过 callback 传递回来(Promise 不支持多次回调),然后拼接 data += str ...
不知道 Deno 会如何解决这个问题,又或者说,在 Deno 中没有 stream 的概念了?
比较好奇,我还是直接装一个 Deno 试试好了
2020年5月 8日 19:19 | # | 引用
zl7261 说:
一门语言兼顾前后端开发本身就是扯淡
没有银弹
也没有万金油语言
我是真的不理解为什么吹node,尤其是我看完了Js puzzle之后
npm这种连照抄maven都不会的包管理
秦皇统一文字的前提是也是大家都是人,都有眼睛鼻子耳朵,都会听说读写.
每个设备的cpu架构都有可能不一样,怎么可能又会一门万金油语言在所有端运行,并且保持运行效率?
2020年5月 9日 11:27 | # | 引用
石常友 说:
windows 7 打开 PowerShell 输入
iwr https://deno.land/x/install/install.ps1 -useb | iex
没成,显示"无法将 iwr 项识别为 cmdlet..."
百度也没找到合适答案
2020年5月 9日 12:51 | # | 引用
kiinlam 说:
deno1.0发布了!
2020年5月14日 14:54 | # | 引用
前端小白 说:
今天真的发布了
2020年5月15日 15:02 | # | 引用
犬来八荒 说:
感觉推行还是得有很长时间的,毕竟npm社区生态已经形成了。。。你要想再转其他的太麻烦了而且npm的各种插件已经很完善,虽然node_modules很恶心。。。。
2020年5月16日 11:21 | # | 引用
蔡九 说:
麻溜的,等不及了
2020年5月16日 13:29 | # | 引用
limuyap 说:
node是09年的东西,火起来都几年后了,照这个规律,deno估计2025年左右才会大火
2020年5月18日 09:53 | # | 引用
时间的灰 说:
尝试将PowerShell升级到5.x,win7默认的PowerShell版本应该是2.0
2020年5月18日 16:27 | # | 引用
Leo 说:
恐龙的读音什么时候变成「帝诺」了。。。「呆诺」才对啊。
2020年5月18日 17:02 | # | 引用
米司特包 说:
真心不喜欢node_mosules deno的这个资源引入方式和golang的相似 个人觉得挺好
2020年5月19日 13:28 | # | 引用
胡斐 说:
import模块的时候, deno当初是否考虑过可以指定默认后缀 .ts/.js
2020年5月20日 12:23 | # | 引用
done 说:
其实deno也只是过渡的,还有一个最终版本done
2020年5月21日 21:08 | # | 引用
白筱汐 说:
nodeJS 回调函数的问题,对于javaScript 熟悉的同学也可以接受,做jquery的时候应该经常接触到。重要的是node_modules 包过于复杂,管理太麻烦。
2020年5月24日 12:45 | # | 引用
阿猫 说:
什么时候开发个dono
2020年5月25日 10:00 | # | 引用
也已 说:
是啊 太痛苦了
2020年5月29日 11:05 | # | 引用
打酱油的Hhh 说:
最近正在学node 我想哭了
2020年6月 1日 15:26 | # | 引用
冰中焱 说:
感觉有点凉。
大学之路:vb、c、c#、sql、webform、js、jq
社会小白之路:js、jq、angular1、vue2、react、react1.6、mysql、redis、node。
社会小白之路2:meteor、egg、rn、flutter。
即将:deno。。。。
我感觉我好难
2020年6月12日 10:54 | # | 引用
Max 说:
沒有module跟package manager好像不是太好吧
如果鏈接死了,沒有備份的話,那個項目就可能要重寫了
而且如果腳本被改了,我們也不知道,會有資安隱憂吧
2020年6月13日 16:20 | # | 引用
Hai Ji 说:
名字略屌,库引用方式比较自由,估计国内会被qiang
2020年6月23日 13:12 | # | 引用
zxy 说:
如果import依赖的文件升级了,怎么办呢?可以指定版本吗?
2020年6月24日 11:26 | # | 引用
邱朗 说:
看到deno最近进展,说启用typescript, 我实在很无语。
https://bit.ly/3hUHdU3
前端开发就是折腾啊
2020年6月24日 11:43 | # | 引用
ypz010 说:
前端就是个大杂烩 真么都往里装 然后越来越臃肿
2020年6月26日 22:25 | # | 引用
tanyh 说:
go v8 会有双层gc问题,所以没办法,才改成rust的
2020年6月28日 15:01 | # | 引用
DOUZI 说:
就是 node还没 用好,又deno , 这太 被动了
2020年6月29日 18:19 | # | 引用
endo 说:
到时候肯定都是自己维护这些模块了,所有依赖模块都必须存放在自己的资源服务器或者cdn。
2020年6月30日 14:12 | # | 引用
Hiya 说:
node => deno => done
2020年7月 6日 21:19 | # | 引用
二进制宇宙 说:
最直接干脆的解决方法: 把JavaScript语言给废除了,重新建一门新的语言。
2020年7月 9日 18:47 | # | 引用
undefined 说:
不得不说deno的logo挺可爱啊
2020年7月15日 11:21 | # | 引用
wumin 说:
依赖,依赖更新怎么解决
2020年7月28日 15:59 | # | 引用
sdutwsl 说:
能被JS改写的 终将被JS改写
2020年8月 6日 09:59 | # | 引用
jingkaimori 说:
有的npm包(比如marked)提供了把模块打包成一个文件的功能,如果可以把exports换成原生的export语句就能在deno里用
2020年8月 8日 15:54 | # | 引用
unde 说:
将要学,但deno这冷水一下来,心凉了一半哈哈
2020年8月13日 11:24 | # | 引用
宁小法 说:
deno 目前最新版本:v1.3.3
真是学无止境...
2020年9月 8日 16:07 | # | 引用
deno 说:
没有中心化的服务器,那第三方包的安全性怎么保证,又怎么去找到这些包
2020年9月23日 16:19 | # | 引用
春续 说:
以后从url管理应当是个趋势吧,用包名本来就挺变态的。
2020年9月29日 17:30 | # | 引用
deno 说:
怎么去维护第三方的包呢?
2020年10月21日 15:14 | # | 引用
yxl-net 说:
本来决定学GoLang的,现在不知道是学GoLang还是Rust,还是两门都学了。
2020年10月31日 09:38 | # | 引用
甜到哀伤 说:
1.6发布了,可以打包为单独文件
2020年12月10日 16:40 | # | 引用
zhaoshidong 说:
通过url加载包,会不会很慢,或者包的地址突然访问不到,都是如何处理的
2021年1月21日 09:27 | # | 引用
Introtec.Tom 说:
既然Deno 是 destroy + node 的缩写,那不应该是蒂诺吗。。。。
2021年1月21日 16:07 | # | 引用
魔方 说:
支持, npm没有那么不堪, 期待node完美支持ES6
2021年2月19日 16:56 | # | 引用
Daben 说:
大佬,deno官網找不到license相關信息
公司的軟件全部都要提供證明開源的license信息給IT部門審核
請問哪裏有deno的license聲明呢
2023年4月27日 13:59 | # | 引用