精读《Deno 1.0 你须要了解的》

1 引言

Deno 是什么?Deno 和 Node 有什么关系?Deno 和我有什么关系?前端

Deno 将于 2020-05-13 发布 1.0,若是你还有上面的疑惑,能够和我一块儿经过Deno 1.0: What you need to know这篇文章一块儿了解 Deno 基础知识。node

但愿你带着疑问思考,将来 10 年看今天,会不会出现 Deno 官方生态壮大,彻底替代 Node 进而影响到 Web 生态的局面呢?这个思考结果会影响到你将来职业发展,你须要学会本身思考,并对这个思考结果负责。react

2 介绍 & 精读

Deno 的做者是 Ryan Dahl,他是 Nodejs 背后的策划者,曾经说过我对 Nodejs 感到遗憾的 10 件事。这也是为何新开一个坑的缘由,但 Deno 并不定位为 Nodejs 的替代品,从总体功能来看,Deno 有更大的野心,据个人推测是想要取代如今陈旧的先后端开发模式,让 Deno 一统先后端开发全流程。webpack

Nodejs 是由 C++ 写的,而 Deno 则是由 Rust 写的,并选择了Tokio这个异步编程框架,并使用 V8 引擎解析 Javascript,并内置了对 Ts 的解析。git

安装

Deno 支持以下安装方式:github

Shell:web

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

PowerShell:shell

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

Homebrew:npm

brew install deno

Chocolatey:编程

choco install deno

脚本执行方式为deno run,能够类比为node,但功能不一样且支持远程文件,实际上远程依赖是 Deno 的一大特点,也是有争议的地方:

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

在 ts 文件中容许用远程脚本加载资源,这个后面还会提到:

import { serve } from "https://deno.land/std@v0.42.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

安全性

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文件夹下的文件拥有文件读权限。

除了直接加参数调用、Bash 脚本调用外,还能够用 Make 运行,或者使用相似的drake启动。

或者使用deno install命令,将脚本转化为一个快捷指令:

deno install --allow-net --allow-read -n serve https://deno.land/std/http/file_server.ts

-n表示--name,能够对这个脚本进行重命名,好比上面的例子中,serve命令就等同于deno run --allow-net --allow-read https://deno.land/std/http/file_server.ts

标准库

Deno 在标准库上颇有特色,对经常使用功能提供了官方版本,保证可用性与稳定性。原文中列出了一些与 Npm 三方库的对比:

image.png

从这个点上来看,Deno 既作运行环境又作基础生态,缓解了 Npm 生态下选择困难症,这件事须要辩证来看:集成了官方包对功能肯定的模块来讲是颇有必要的,并且提升了底层库的稳定性;但 Deno 生态也有三方库,并且本质上三方库和官方库在功能上没有任何壁垒,由于实现代码都相似,惟一区别是谁能为其稳定性站台,假设微软和 Deno 同时出了基于 Npm 生态与 Deno 生态官方库,都保证会持续维护,你更相信谁呢?官方是否有优点要取决于官方自身的实力。

内置 Typescript

Deno 内置支持了 TS,所以不须要ts-node咱们就能够用deno run test.ts运行 Typescript 文件。值得注意的是,Deno 内部也是利用 Typescript 引擎解析为 Js 后交由 V8 引擎解析,所以本质上没太大的变化,只是这样 Deno 的生态会更规范。

因为内置了 TS 支持,天然也不须要写tsconfig.json配置了,但你依然能够定制它:

deno run -c tsconfig.json [file-to-run.ts]

Deno 默认还开启了 TS 严格模式,因此看到这里,能够认为 Deno 是为了构建高质量理想库而诞生的运行环境,基于已有的生态来作,但作了更多内置技术选型,这和 Facebook 的rome很像,但作的却更完全。

其实从实现上来看,咱们基于 Javascript 生态也能写出deno run test.ts这样相似的引擎,只不过是由 JS 驱动执行,可能编译还会选择 Webpack,但 Deno 自己基于 Rust 实现,并从新实现了一套模块加载标准,能够说从更底层的方式从新解读了 W3C 标准规范,以指望解决 Javascript 生态的各类痛点问题。

支持 Web 标准

Deno 还支持 W3C 标准规范,所以像fetchsetTimeout等 API 均可以被直接使用,若是你按照 Deno 支持的那几个函数写代码,能够保证在 Deno、Node、Web 三个平台实现跨平台运行。

虽然距离彻底实现 W3C 全部标准规范还有一些路要走,但咱们看到了 Deno 兼容规范的决心。

ESModule

模块化是 Deno 的亮点,Deno 使用官方 ESModule 规范,但引用路径必须加上后缀:

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

Deno 不须要申明依赖,代码的引用路径就是依赖申明,会包括完整的路径以及文件后缀,也支持网络资源,能够摆脱 NPM 中心化的包管理模式,由于这个路径能够是任何网络地址。

包管理

对于import * as log from "https://deno.land/std/log/mod.ts";这行代码,Deno 会下载到一个缓存文件夹,用户不会感知到这个文件夹与这个过程的存在,也就是说,Deno 环境中是没有node_modules的。

也能够经过deno --reload的方式强制刷新缓存。

但这里也要辩证的看待 “Deno 去中心化” 这件事,虽然引用了网络源,但会引起下面几个问题:

  1. 实际上还存在一个 "node_modules",只是用户看不到。
  2. 网络下载速度放到运行时,第一次启动仍是很慢。
  3. 普通模式下无 lock,必须配合deps.ts使用,这个后面会提到。

即便被打上 “中心化恶人” 的 npm 也有去中心化的一面,由于 npm 支持私有化部署,不管是速度仍是稳定性均可以由公司本身掌控,从稳定性来讲仍是 npm 拥有压倒性优点。

三方库

Deno 还有第三方库生态,截止目前共有221 个三方库 "%5B%5D(https://deno.land/x/)")。

因为 Deno 走网络资源,咱们能够借助Pika提供的 CDN 服务直接引用网络资源包:

import * as pkg from "https://cdn.pika.dev/preact@^10.3.0";

虽然这样看上去很轻量,但对公司来讲仍是须要自建一个 “Pika” 保障稳定性,以及作全球 CDN 缓存等的工做。

告别 package.json

npm 生态下包信息存放在package.json,包含但不限于下面的内容:

  • 项目元信息。
  • 项目依赖和版本号。
  • 依赖还进行分类,好比dependenciesdevDependencies甚至peerDependencies
  • 标记入口,mainmodule,还有 TS 用的typestypings,脚手架的bin等等。
  • npm scripts。

随着标准的不断更新,package.json信息已经很是臃肿了。

对于 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";

deps.ts就是一个普通文件,只是将项目的依赖精确描述出来,这样其余地方引用assert时,就能够这么写了:

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

若是须要锁定依赖,能够经过deno --lock=lock.json方式申明。

deno doc

deno doc <filename>命令能够根据文件按照 JS Doc 规则生成文档,同时也支持 TS 语法,好比下面这段代码:

/** 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.

deno 自己文档就是用这个命令生成的,能够访问官方文档查看使用效果。

内置工具链

前端 Javascript 工具链至关混乱,虽然业界已有 Umi 等框架作了开箱即用的封装,但回到 Javascript 设计的初衷就是能够在浏览器直接使用的,包括浏览器对不依赖构建工具的模块化支持,注定了将来 Webpack 必定会被消灭。

Deno 经过内置一套工具链的方式解决这个问题,包括:

  • 测试:提供deno test命令与Deno.test()测试函数。
  • 格式化:提供vscode 插件
  • 编译:提供deno bundle命令。

不过值得注意的是,在最重要的编译环节,deno bundle目前提供的能力是相对欠缺的,好比还不支持 Tree Shaking。

用 Rust 等语言提高构建效率是业界一直在尝试的事,好比 @陈成 就基于esbuild作了@umijs/plugin-esbuild插件用于提高 Umi 构建速度,但为了防止生产构建产物与 Webpack 默认规则不一致,仅使用了其压缩(minifier)功能。

对 deno 来讲也同样,目前其实没有任何证据代表 deno 的构建结果能够完美适配 webpack 环境,因此请勿认为 deno 发布了 1.0 版本就等于能够在生产环境使用。

3 总结

正如原文结尾所说的,Deno 虽然将要发布 1.0 版本,但仍不能彻底替代 Nodejs,这背后的缘由主要是历史兼容成本,也就是完整支持整个 Node 生态不仅是设计的问题,更是一个体力活,须要一个个高地去攻克。

一样 Deno 对 Web 的支持也让人耳目一新,但仍不能放到生产环境使用,除了官方和三方生态还在逐渐完善外,deno bundle对 Tree Shaking 能力的缺失以及构建产物没法保证与如今的 Webpack 彻底相同,这样会致使对稳定性要求极高的大型应用迁移成本很是高。

最亮眼的改动是模块化部分,依赖彻底去中心化从长远来看是一个很是好的设计,只是基础设施和生态要达到一个较为理想的水平。

最后,让咱们站在一个预言者角度思考一下 Deno 到底会不会火吧:

Deno 作的初心是作一个更好的 Node,但很不信,对于这种级别的生态底层工具来讲,从新作一个并从新火起来的难度,不亚于从新作一个阿里巴巴并取代如今阿里的难度。也就是不一样的时间点作同一件事,哪怕后者能够吸收教训,大几率也没法复制之前成功的路线。

从 Deno 的功能来看,解决了 Node 不少痛点,其中就包括去中心化管理,有点云开发的意思,但在 2020 年,基于 Nodejs 和 Webpack 的云开发都搞出来了,说实话是没有 Deno 什么空间的。从功能上来看,开篇就说了 Deno 基于 V8 解析 Javascript,对于性能和功能都没有革命性提高,从技术上做出突破也几乎不可能了。

Deno 的思想确实比 Node 先进,但不能说比 Node 好十倍,则没法撼动 Node 的生态,即使是 Node 做者本身可能也不行。

然而我上面说的可能都是错的。

相关文章
相关标签/搜索