本篇文章参考以下博文
前言
前段时间 Deno1.0 发布了,作为前端小白,连 Node 都还没掌握熟练,不知道哪来的勇气,居然对 Deno 蠢蠢欲动。可能由于最近处在学习 Node 的蜜月期,对于这方面知识兴致正浓,所以就翻了 Deno 的牌子。写下本篇博客,记录一下我的作死学习路。
前世今生
Deno 的创作者,也是 Node 的创作者之一,Ryan Dahl,Web 界的一名天降猛男。
创建出 Node 之后,在最火的时代,转战 GO 专心研究人工智能。现在回来再捡起 Node 发现这个项目已经背离了他的初衷,有一些无法忽视的问题。
首先 JavaScript 语言脱胎换骨,ES6 标准引入了大量新的语法特性。其中,影响最大的语法有两个:Promise 接口(以及 async 函数)和 ES 模块。
Node 对于上面两个语法不太友好,Node 必须支持回调函数(callback ),导致异步接口会有 Promise 和回调函数两种写法;同时,Node 自己的模块格式 CommonJS 与 ES 模块不兼容,导致迟迟无法完全支持 ES 模块。
最终由于 Node 的种种问题,这位猛男决定从头写一个替代品,解决这些问题。Deno 应运而生。
一、安装
使用 Shell ( macOS 和 Linux ):
curl -fsSL https://deno.land/x/install/install.sh | sh
使用 PowerShell ( Windows ):
iwr https://deno.land/x/install/install.ps1 -useb | iex
更新与更新到指定版本
deno upgrade
deno upgrade --version 1.0.1
二、Deno新特性
Deno 相比于 Node ,默认是安全的,这就决定了 Deno 的权限要专门去启用,尤其对于一些敏感区域或功能,需要使用在命令行上授予 deno 进程的权限。
权限清单
可以使用以下权限:
-A,-- allow -all 允许所有权限。这将禁用所有安全性。
--allow-env 允许环境访问,例如获取和设置环境变量。
--allow-hrtime 允许高分辨率时间测量。高分辨率时间可用于定时攻击和指纹识别。
--allow-net = <允许网络> 允许网络访问。您可以指定一个可选的,用逗号分隔的域列表,以提供允许域的允许列表。
--allow-plugin 允许加载插件。请注意–allow-plugin是一个不稳定的功能。
--allow-read = <允许读取> 允许文件系统读取访问。您可以指定目录或文件的可选逗号分隔列表,以提供允许的文件系统访问的允许列表。
--allow-run 允许运行子进程。请注意,子流程未在沙箱中运行,因此没有与deno流程相同的安全限制。因此,请谨慎使用。
--allow-write = <允许写> 允许文件系统写访问。您可以指定目录或文件的可选逗号分隔列表,以提供允许的文件系统访问的允许列表。
Deno run --allow-read mod.ts //允许读取文件
生命周期
Deno 支持与浏览器兼容的生命周期事件: load 和 unload 。我们可以使用这些事件在程序中提供设置和清除代码。这意味着, Deno 可以访问到 window 作为全局对象了, Node 的全局对象是 global ,而 JS 中又没有 global 对象, 之前会存在一些不统一的情况,比如在服务端渲染的时候, node 就不会解析 window ,而且要避免把 window 写入到 node 的模板字符串中,防止解析报错。
import "./imported.ts";
const handler = (e: Event): void => {
console.log(`got ${e.type} event in event handler (main)`);
};
window.addEventListener("load", handler);
window.addEventListener("unload", handler);
window.onload = (e: Event): void => {
console.log(`got ${e.type} event in onload function (main)`);
};
window.onunload = (e: Event): void => {
console.log(`got ${e.type} event in onunload function (main)`);
};
console.log("log from main script");
异步处理
Deno 支持 async 啦!!!可喜可贺,解决了 Node 的一个头疼问题
import { delay } from "https://deno.land/std@0.65.0/async/delay.ts";
Deno.test("async hello world", async () => {
const x = 1 + 2;
// await some async task
await delay(100);
if (x !== 3) {
throw Error("x should be equal to 3");
}
});
管理依赖关系
在 Deno 中,没有包管理器的概念,外部模块会直接导入到本地模块中。这就提出了一个问题,即如何在没有包管理器的情况下管理远程依赖关系。在具有许多依赖性的大型项目中,如果将模块全部单独导入到单个模块中,则更新模块将变得繁琐且耗时。( Node 中模块依赖管理就很头疼)
在 Deno 中解决此问题的标准做法是创建一个 deps.ts 文件。此文件中引用了所有必需的远程依赖关系,并且重新导出了所需的方法和类。然后,从属本地模块将引用 deps.ts 而不是远程从属。
这样就可以轻松跨大型代码库更新模块,并解决“程序包管理器问题”(如果存在)。开发依赖项也可以在单独的 dev_deps.ts 文件中进行管理。
/**
* deps.ts re-exports the required methods from the remote Ramda module.
**/
export {
add,
multiply,
} from "https://x.nest.land/ramda@0.27.0/source/index.js";
总结
本文只是整理了一些 Node 中的痛点问题,其实 Deno 的功能远不止这些,包括 TypeScript , ES6 等功能, Deno 都做了适配和兼容,不过现在有个比较凸显的问题是,目前 Deno 不兼容 Node ,这就有点头疼,不利于后期的发展部署,不过对于一项新技术,有很多问题需要处理,期待后续的版本中 Deno 还能带来一些意外的惊喜。
文中不足支持,欢迎各位前辈指点,我会及时改正。