Welcome to Deno World

1 / What is Deno

2 / Why is Deno

3 / How is Deno

Deno 究竟是什么

What is Deno

V8 上一个安全的 TypeScript 运行时

Deno 的特点

  1. 安全
  2. 支持开箱即用的 TypeScript
  3. 只分发一个独立的可执行文件
  4. 内建工具箱
  5. 内置标准模块
  6. 脚本代码可被打包为一个单独的 JavaScript 文件

Deno 的目标 - 以安全为例

利用 JavaScript 是一个安全沙箱的事实

  • 默认情况下,应该在没有任何网络或文件系统写权限的情况下运行脚本

  • 用户可以选择通过标志访问:--allow-net --allow-write

  • 这允许用户运行不受信任的实用程序

 

不允许将任意原生函数绑定到 V8

  • 所有的系统调用都是通过消息传递完成的(protobuf 序列化)

  • 用两个原生函数支持:send 和 recv

  • 简化设计

Deno 的架构

V8 上的一个 TypeScript 运行时

V8 是一个由 Google 开发的开源 JavaScript 引擎,其在运行之前将 JavaScript 编译成了机器代码,而非字节码或是解释执行它,以此提升性能。更进一步,使用了如 Inline Cache 等方法来提高性能。有了这些功能,JavaScript 程序与 V8 引擎的速度媲美二进制编译。在 Deno 中,V8 引擎用于执行 JavaScript 代码。

Deno 的架构

采用 Rust 开发

Rust 是由 Mozilla 主导开发的通用、编译型编程语言。设计准则为 “安全、并发、实用”,支持函数式、并发式、过程式以及面向对象的编程风格。Deno 使用 Rust 语言来封装 V8 引擎,通过 libdeno 绑定,我们就可以在 JavaScript 中调用隔离的功能。

Deno 的架构

利用 Tokio 构建事件循环系统

Tokio 是 Rust 编程语言的异步运行时,提供异步事件驱动平台,构建快速,可靠和轻量级网络应用。利用 Rust 的所有权和并发模型确保线程安全。Tokio 构建于 Rust 之上,提供极快的性能,使其成为高性能服务器应用程序的理想选择。在 Deno 中 Tokio 用于并行执行所有的异步 IO 任务。

Deno 的架构

为什么是 Deno

Why is Deno

什么是 Node.js

Node.js

V8 上一个 JavaScript 运行时

运行于服务端的 JavaScript

const http = require('http');

http.createServer(function (request, response) {

    // 发送 HTTP 头部 
    // HTTP 状态值: 200 : OK
    // 内容类型: text/plain
    response.writeHead(200, {'Content-Type': 'text/plain'});

    // 发送响应数据 "Hello World"
    response.end('Hello World\n');
}).listen(8888);

// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');

一个简单的 Node.jS 示例

But...

Node.js 历史概览

  • 2009年3月,Ryan Dahl 在博客宣布准备基于 V8 创建一个轻量级 Web 服务器并提供一套库

  • 2009年5月,Ryan Dahl 在 GitHub 上发布了最初版本

  • 2010年底,Ryan Dahl 加入 Joyent 公司全职负责 Node 的发展

  • 2011年7月,Node 在微软支持下发布了 Windows 版本

  • 2011年11月,Node 超越 Ruby on Rails,成为 GitHub 上关注度最高的项目

  • 2012年1月底,Ryan Dahl 在对 Node 架构设计满意的情况下,将掌门人身份转交给 Isaac Z Schlueter(NPM 作者),自己转向一些项目研究

  • 2018年初,Ryan Dahl 开始重新使用 Node

  • 2018年6月,JSConf EU 上 Ryan Dahl 表示 Node 存在太多设计错误了

JSConf EU 2018

回到2018年的那个夏天

Design Mistakes in Node

没有坚持 Promise                             

 

2009.6 Node 中添加了 Promise

2010.2 Promise 被删除

Promise 是 async/await 的必要抽象

标准化与 async/await 受其影响

Design Mistakes in Node

require("module") 不符合 Web 标准且不明确

Design Mistakes in Node

无底洞的 node_modules

Design Mistakes in Node

没有利用好 V8 沙箱的优势               

GYP 指导用户编写 C++ 来绑定到 V8

冗余的 package.json

冗余的 index.js

……

Deno 的最新动态

How is Deno

在努力做好(Deno)这件事和推出一款可用的产品之间很难取得平衡。因为还没有在开发工具支持特性上取得实质进展,官方团队再次推迟发布日期。官方团队进行了详细的讨论,得出结论是 2 个月的时间足够了。巧合的是,这是自 Deno 问世以来的两周年纪念日。因此,我们将 2020 年 5 月 13 日定为 1.0 版本发布日期。我们鼓励贡献者在 4 月 20 日之前对 API 进行重大修改——在那之后,我们将对 API 进行完善和 bug 修复。当然,在 1.0 之后,API 将继续发展和改进,但是我们将为一些接口提供显式的稳定性保证。

https://deno.land/v1

2020年5月13日,Deno 1.0 如期而至

GitHub https://github.com/denoland/deno

作为普通开发者,有什么我们需要了解的?

Deno 支持多种安装方式

// Shell:

curl -fsSL https://deno.land/x/install/install.sh | sh

// PowerShell:

iwr https://deno.land/x/install/install.ps1 -useb | iex

// Homebrew:

brew install deno

// Chocolatey:

choco install deno

// 脚本执行方式为 deno run,可以类比为 node,但功能不同且支持远程文件:

deno run https://deno.land/std/examples/welcome.ts

安全的 Deno

// Deno 是默认安全的,这体现在默认没有环境、网络访问权限、文件读写权限、运行子进程的能力。所以如果直接运行一个依赖权限的文件会报错:

deno run file-needing-to-run-a-subprocess.ts

# error: Uncaught PermissionDenied: access to run a subprocess, run again with the --allow-run flag

// 可以通过参数方式允许权限的执行,有 --allow-read、--allow-write、--allow-net 等:

deno --allow-read=/etc

// 上面表示 /etc 文件夹下的文件拥有文件读权限。

Deno 的标准库

包管理与三方库

// deps.ts
export { assert } from "https://deno.land/std@v0.39.0/testing/asserts.ts";
export { green, bold } from "https://deno.land/std@v0.39.0/fmt/colors.ts";

// 使用
// import { assert } from "https://deno.land/std@v0.39.0/testing/asserts.ts";
import { assert } from "./deps.ts";

// 锁定依赖
deno --lock=lock.json

Deno “去中心化”的包管理会自动处理依赖缓存,添加 --load 便可强制刷新缓存

三方库不再需要 package.json,用 deps.ts 来集中管理依赖

ESModule

import * as log from "https://deno.land/std/log/mod.ts";
import { outputToConsole } from "./view.ts";

Deno 使用官方 ESModule 规范,但引用路径必须加上后缀

Deno 不需要声明依赖,代码引用路径便是依赖声明

文档

// 代码文件
/** Asynchronously fulfill a response with a file from the local file
 * system. */
export async function send(
  { request, response }: Context,
  path: string,
  options: SendOptions = { root: "" }
): Promise<string | undefined> {
  // ...
}

// 生成文档
function send(_: Context, path: string, options: SendOptions): Promise<string | undefined>
Asynchronously fulfill a response with a file from the local file system.

读取文件按照 JS Doc 规则生成文档,并支持 TS 语法

内置 TypeScript,不再需要 ts-node

支持 Web 标准,比如 fetch、setTimeout 等

内置工具链支持,如测试、格式化、编译等

……

其他

关于 Deno 我还想了解更多

Ref

  1. Deno 安全设计解释图来自 Ryan JSConf EU 2018 演讲稿 https://tinyclouds.org/jsconf2018.pdf
  2. Deno 架构源自 deno.land https://deno.land/manual/contributing/architecture
  3. Deno 标准库截取自 LogRocket 文章 https://blog.logrocket.com/deno-1-0-what-you-need-to-know/
  4. 部分 Deno 标识截取自 https://www.htmlhints.com/article/getting-started-with-deno-10/91
  5. 其余参考内容见前页

Q&A