网站首页 > 知识剖析 正文
这几天假期,我学习了一下 Deno[1]。它是 Node.js 的替代品。有了它,将来可能就不需要 Node.js 了。
这篇文章就是 Deno 的一个初步介绍,尝试回答为什么 Node.js 不能满足需要,以及 Deno 能够带给我们什么?
以下内容主要基于 Bert Belder[2]和 Ryan Dahl[3]的最新演讲。
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[4]库,来实现事件循环(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 的安装可以参考官网首页[5],但是你可以直接去 GitHub 仓库的发布页[6],下载编译好的可执行文件(上图)。
下载 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 的远程脚本,这是官网给出的例子[7]。
$ 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 更具优势。
参考资料
[1]
Deno: https://deno.land/
[2]
Bert Belder: https://www.youtube.com/watch?v=puXyo1jGQys
[3]
Ryan Dahl: https://www.youtube.com/watch?v=1gIiZfSbEAE
[4]
Tokio: https://github.com/tokio-rs/tokio
[5]
官网首页: https://deno.land/
[6]
发布页: https://github.com/denoland/deno/releases
[7]
例子: https://deno.land/std/examples/curl.ts
- 上一篇: 33. 教你零基础搭建小程序:页面的生命周期(1)
- 下一篇: 微信小程序生命周期学习笔记-页面篇
猜你喜欢
- 2024-11-17 Android对so体积优化的探索与实践
- 2024-11-17 JavaScript对象(javascript对象主要包括)
- 2024-11-17 前端埋点统计方案思考(前端数据埋点)
- 2024-11-17 第27节 函数、作用域及垃圾回收-Javascript-零点程序员-王唯
- 2024-11-17 微信小程序学习笔记:Page()(小程序 page)
- 2024-11-17 广州蓝景分享—搞懂js事件、事件流(捕获冒泡)、事件委托
- 2024-11-17 程序员都必掌握的前端教程之JavaScript基础教程(下)
- 2024-11-17 DOM核心内容(dom的核心部分包括)
- 2024-11-17 小程序生命周期解析(从概念、启动、运行、销毁场景的全面解析)
- 2024-11-17 微信小程序学习笔记(二)——开发之框架
- 04-29php开发者composer使用看这一篇就够了
- 04-29引用和变量声明在不同语言中的实作
- 04-29PHP 没你想的那么差
- 04-29Ubuntu linux 上的 Nginx 和 Php 安装
- 04-29CentOS下通过yum搭建lnmp(单版本PHP)
- 04-29为什么 PHP8 是个高性能版本
- 04-29PHP8函数包含文件-PHP8知识详解
- 04-29使用无参数函数进行命令执行
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)