🕵️♂️一块儿认识Deno

动态语言都是很是实用的工具,用户能够经过脚本把很是复杂的系统给连接到一块儿,而且不用花费心思去考虑内存管理等问题。html

JavaScript 是应用最普遍的动态语言,只需一个 Web 浏览器就能在全部设备上运行。而Node.js是一个基于Chrome V8引擎的JavaScript运行时(能够理解为一个容器,提供JavaScript解析+各类能力)。前端

🤔️Node.js怎么了?

image.png

Node.js诞生2009年,它的到来对前端领域产生了很是重大的影响,它也使得先后端使用同一种语言,统一模型的梦想得以实现。可是在这十多年间,强大的Node.js也慢慢地暴露出了它的缺点。在2018年,Node.js之父Ryan Dahl发表了一篇演讲,在此次演讲中他提到了“Node.js令我感到遗憾的10件事”。node

1. 没有坚持使用Promise

在Node.js中,对于异步处理同时存在两种方式:callback写法与Promise写法。在8.0版本之前,Node.js的异步API基本上都是用callback的方式来写的:webpack

fs.readFile('文件.txt', data, (err) => {
  if (err) throw err;
  console.log('文件已被保存');
});
复制代码

为了靠近Promise,一方面Node.js慢慢增长了一部分Promise写法的API,另外一方面在util包中增长了一个promisify接口用于把回调方式的API转换为Promise方式:git

const {promisify} = require('util')
const readFile = promisify(fs.readFile)
readFile('./conf.js').then(data=>console.log(data))
复制代码

2. 没有足够的安全性

在Node.js中,任何人编写的程序均可以随意地访问系统和网络,这将会很容易致使安全问题。例如:假如咱们经过npm安装了一个依赖a-mod,但不少状况下咱们并不知道这个包内部的代码逻辑是怎么样的,它有可能会在提供服务的同时,在咱们绝不知情的状况下偷偷地删除咱们本地的文档(只是恶趣味),甚至更危险的事情。github

3. node_modules

随着Node.js的发展,node_modules很容易变得愈来愈大愈来愈沉重,而且模块的解析复杂度也在随着它增大而增大。web

image.png

......

🤯Deno又是啥?

2020年5月13日,Deno 1.0正式发布,它正是出于咱们上文中提到的Node.js的做者Ryan Dahl之手。而Deno与Node.js同样,都是一个基于Chrome V8引擎的JavaScript运行时。经过它的名字(no与de的拼接),结合做者在18年时对Node.js的吐槽,虽然咱们不能认定Deno会是Node.js的替代品,可是它确定是一个避免了Node.js某些设计缺陷的新尝试。npm

1. 统一使用Promise接口

与Node.js不一样,Deno统一使用Promise接口,配合async写法使得整个系统变得流畅和统一了。编程

// Deno.create方法能够建立或读取一个文件
const file = await Deno.create("./foo.txt");
console.log(file);
复制代码

值得一提的是,Deno支持 top-level-await,即咱们能够直接在最外层代码中使用await关于top-level-await的更多信息能够参考如下文章:Top-level awaitjson

2.内置Typescript

若是咱们要在 Deno 中使用TypeScript的话,无需执行任何操做。没有Deno时,咱们必需要将咱们编写的TypeScript代码编译为JavaScript才可以运行。Deno将会直接在它内部进行这个编译的过程,下降了上手的成本。

3. 兼容ES6模块语法

Node.js模块遵循的是CommonJS规范,这就致使了它没法完美兼容ES6的module语法。而Deno使用了TypeScript语言,这将彻底兼容ES模块(TypeScript也有一套它本身的模块管理规范,但同时兼容ES6 module语法)。若是想要再了解一下这些模块管理规范的区别的话,能够参考如下文章:exports、module.exports 和 export、export default 究竟是咋回事

4.再也没有node_modules

咱们在使用Node.js时,一般每一个工程都须要经过npm i来安装所需依赖。npm的存在的优势是集思广益,极大地丰富了Node.js生态,为使用者提供了又大又全的功能。可是它也有一些缺点,例如它致使全世界都被node_modules占领了:一个发布到npm上的包在全世界无数台电脑上都有它各类版本的副本,这正是中心化的模块存储方式形成的。

Deno采用不强制中心化存储方式,换句话说你能够加载任何地方的模块。

// 能够直接经过url引入
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
复制代码

它具备如下特色:

  • 再也不有中心化的包管理器了。你能够直接经过url导入ECMAScript模块;

  • 再也不有“神奇的”Node.js 模块解析。如今语法是明确的,这让各类事情更容易推理;

  • 再也不有node_modules目录;

上述第一点提到的去中心化能够说是Deno做出的一次勇敢的尝试,可是它其实也有一些问题:

  • 实际上还存在一个node_modules(下文会提到)只是不会被用户轻易看到;
  • 正常来讲依赖的下载会放在第一次加载的时候(也能够经过deno cache命令在不执行代码的状况下缓存依赖),因此总体看来第一次启动仍是很慢的;
  • 很难控制版本,须要配合 deps.ts 使用(下文会提到);

既然Deno并无node_modules,那么总得有一个地方存放依赖吧?

其实存放依赖的目录是经过DENO_DIR这个环境变量来控制的(其实也是node_modules),它的初始值为 $HOME/.deno

咱们能够经过如下命令,查看当前电脑已经缓存的依赖:

tree $HOME/Library/Caches/deno
复制代码

image.png

5. 使用dep.ts和url进行版本控制

基本上咱们每一个工程都是围绕package.json创建的。它已经膨胀得很大了,其中包含许多职责,诸如:

  • 保留项目的元数据;

  • 列出项目依赖项和版本控制;

  • 将依赖项分类为dpendenciesdevDependencies

  • 定义程序的入口点;

  • 存储与项目相关的 Shell 脚本;

  • ......

相比于package.json最先的用意(可能只是描述一个包信息而已),它变得过于复杂。Deno选择将它抛弃,利用deps.ts取而代之,进行版本控制(和咱们工程中Constant.js差很少)。

在内部,依赖项被从新导出。这就能让应用程序中的不一样模块都引用相同的源。

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中更改url。

6. 具备安全机制

默认状况下 Deno 中的代码会在安全的沙箱中执行。未经容许,脚本没法访问硬盘驱动器、打开网络链接或进行其余任何可能引入恶意行为的操做。浏览器提供了用于访问相机和麦克风的 API,但用户必须首先授予权限才能启用它们。Deno在终端中提供了模拟行为。

要查看权限示例的完整列表,请输入如下命令:

deno run -h
复制代码

image.png

7. 提供一套内置工具

在咱们开发的过程当中,不少时候须要使用一些实用工具(例如:webpack,babel,eslint,prettier......),Deno 内置了开发者须要的各类功能包括打包、格式美化、测试、安装、文档生成等软件生命周期的各类功能。

deno bundle:将脚本和依赖打包
deno eval:执行代码
deno fetch:将依赖抓取到本地
deno fmt:代码的格式美化
deno help:等同于-h参数
deno info:显示本地的依赖缓存
deno install:将脚本安装为可执行文件
deno repl:进入 REPL 环境
deno run:运行脚本
deno test:运行测试
复制代码

Deno 自己就是一个完整的生态系统,具备运行时和本身的模块/包管理系统。这才有了更大的空间来内置全部工具。

虽然目前尚未办法在Deno中替换整个前端构建管道,可是随着Deno生态的发展,相信这一天已经不会太远了。

8. 更靠近JavaScript API

Deno是精心设计的,避免偏离标准化的浏览器JavaScript API。Deno 1.0 提供如下与 Web 兼容的 API:

  • addEventListener
  • atob
  • btoa
  • clearInterval
  • clearTimeout
  • dispatchEvent
  • fetch
  • queueMicrotask
  • removeEventListener
  • setInterval
  • setTimeout
  • AbortSignal
  • Blob
  • File
  • FormData
  • Headers
  • ReadableStream
  • Request
  • Response
  • URL
  • URLSearchParams
  • console
  • isConsoleInstance
  • location
  • onload
  • onunload
  • self
  • window
  • AbortController
  • CustomEvent
  • DOMException
  • ErrorEvent
  • Event
  • EventTarget
  • MessageEvent
  • TextDecoder
  • TextEncoder
  • Worker
  • ImportMeta
  • Location

这些均可以在程序的顶级范围内使用。这意味着若是你不去用Deno()命名空间上的任何方法,那么你的代码应该能同时与Deno和浏览器兼容。尽管这些Deno API并非都 100%符合其等效的Web规范,但这对前端开发人员而言仍然是一个很大的好处。

整体而言,若是服务端和浏览器端存在相同概念,Deno就不会创造新的概念。这一点其实Node.js也在作,旨在实现 Universal JavaScriptSpec compliance and Web Compatibility的思想,这是一个大趋势。

9.标准库

Deno团队为开发者提供了一个没有外部依赖的、实用的、高频的开发库,减轻咱们开发的负担:

  • node:node API 兼容模块;
  • io:二进制读写操做;
  • http:网络和 web 服务相关;
  • path:文件路径相关;
  • colors:输出有颜色的文字,相似 chalk 库;
  • printf:格式化输出,相似 C 语言的 printf;
  • tar:解压与压缩;
  • async:生成异步函数的;
  • bytes:二进制比较和查找等;
  • datetime:日期相关;
  • encoding:文本的与二进制的转化、CSV和对象转化、yarml 和对象转化等;
  • flags:命令行参数解析;
  • hash:字符转 sha1 和 sha256;
  • fs:文件系统模块,相似 node 的 fs 模块;
  • log:日志管理;
  • permissions:权限相关;
  • testing:测试和断言相关;
  • uuid:用于生成 UUID;
  • ws:WebSocket 相关;

从这个点上来看,Deno 既作运行环境又作基础生态,有效缓解了npm生态下选择困难症。集成了官方包对功能肯定的模块来讲是颇有必要的,并且提升了底层库的稳定性,除此以外Deno生态也有三方库,并且本质上三方库和官方库在功能上没有任何壁垒,由于实现代码都是相似的。

......

🤩总结

如下图片归纳了Node与Deno之间的差别:

image.png

Deno的出现使人振奋,可是它仍不能彻底替代 Nodejs,这背后的缘由主要是历史兼容成本,也就是完整支持整个Node生态不仅是设计的问题,更是一个体力活,须要一个个高地去攻克。

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

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

尽管Deno可能还没法彻底替代Node.js,但它已经成为了能够平常使用的绝佳编程环境。

😘参考文档

相关文章
相关标签/搜索