特性与优缺点
特性
Deno含有以下功能亮点:
-
默认安全。外部代码没有文件系统、网络、环境的访问权限,除非显式开启。
-
支持开箱即用的TypeScript的环境,尽管它仍需要编译为JavaScript才能运行,但这是在内部完成的,因此对用户来说TypeScript的行为就好像它是原生支持的一样。
-
只分发一个独立的可执行文件(deno)。
-
有着内建的工具箱,比如一个依赖信息查看器(deno info)和一个代码格式化工具(deno fmt)。
-
有一组经过审计的标准模块,保证能在Deno上工作。
-
脚本代码能被打包为一个单独的JavaScript文件。
安全性
默认情况下,Deno是安全的。相比之下,Node.js拥有对文件系统和网络的完全访问权限。要在没有权限的情况下运行程序,请使用:
deno run file-needing-to-run-a-subprocess.ts
如果代码需要权限设置,则会提醒你。
error: Uncaught PermissionDenied: access to run a subprocess, run again with the –allow-run flag
Deno使用命令行选项来显式许可访问系统的各个部分。最常用的包括:环境访问
网络访问,文件系统读/写访问,运行一个子进程,要查看权限示例的完整列表,请输入deno run -h。
这里的最佳实践是在read、write和net上使用权限白名单。这样你就可以更清楚地了解Deno被允许访问哪些内容。例如,要允许Deno在/etc目录中只读文件,请使用:deno –allow-read=/etc
标准库
Deno标准库是由Deno项目维护,并保证可用于Deno的常用模块集合。它涵盖了用户最常用的常见任务代码,并且是基于Go编程语言提供的标准库。JavaScript一直以来困扰用户的一个问题就是缺乏标准库。用户被迫一次又一次地重新发明轮子,开发人员不得不经常在npm上搜索第三方模块,以解决本应由平台制造商解决的常见问题。
React之类的库可以解决很多复杂问题,这些第三方包很好用。但是对于UUID生成等简单的事情来说,我们最好使用官方的标准库。这些小型库可作为大型库的构建块,从而加快了开发速度并减少了开发人员的负担。曾一度流行的库被遗弃,留给用户自己维护或者需要用户找一个替代品的事情时有发生。
内置TypeScript
TypeScript是添加了显式类型的JavaScript。任何有效的JavaScript代码也是有效的TypeScript代码,因这个将你的代码转换为TypeScript是非常容易的。只需将扩展名更改为.ts并开始添加类型即可。
要在Deno中使用TypeScript无需执行任何操作。没有Deno时,必须将TypeScript编译为JavaScript才能运行。Deno会在内部为你完成这个步骤,让TypeScript更容易上手。
尽可能使用Web标准
创建一个Web标准需要很长时间,但一旦标准被确定下来,我们就不应该忽略它。虽然框架来来去去,但Web标准是会长期存在的。花费在学习标准化API上的时间永远不会白费,因为没有人敢于破坏Web;它可能已经使用了数十年,甚至可能在你剩下的职业生涯中一直发光发热。
fetch这个Web API提供了用于提取资源的接口。浏览器中有一个JavaScript fetch()方法。如果你想在Node.js中使用这个标准,则需要使用第三方库Node Fetch。在Deno中它是内置的,并且就像浏览器版本一样开箱即用。
ECMAScript模块
相比Node.js,Deno的一项主要进步是它使用了官方的ECMAScript模块标准,而不是老式的CommonJS。Node.js直到2019年底才在13.2.0版本中启用ECMAScript模块,但支持还是不够成熟,并且仍然包含有争议的.mjs文件扩展名。
Deno在模块系统中使用了现代Web标准,从而避免了旧时代的影响。模块使用URL或文件路径引用,并包含必需的文件扩展名。例如:
import * as log from "https://deno.land/std/log/mod.ts";
import { outputToConsole } from "./view.ts";
缺点
包管理器
Deno包管理器的主要问题是,它在CI/CD中很难用。我的意思是,如果你需要快速执行CI/CD,则必须将所有软件包手动加载到你的应用Git中(否则,每次CI/CD启动后开发人员和测试人员都需要等待从网络加载所有内容——这只是在浪费开发时间和预算)。如果选择Git这个选项,那么你的开发人员需要像上世纪那样手动进行所有升级(或者干脆换成带有NPM的Node.js)。
import { connect } from "https://deno.land/x/amqp/mod.ts";
import * as base64 from "https://denopkg.com/chiefbiiko/base64/mod.ts";
import { createLogger } from "https://denolib.com/yamboy1/deno-structured-logging/mod.ts";
...
另外,我不喜欢Deno不在一个文件中指示所有包的做法。在大型企业级应用程序中这是会造成混乱的。试想一下,超过20位开发人员无需任何系统化方法即可导入软件包。而且根本没有版本控制(仅在某些URL中或手动创建的带有依赖项文件中才有,这不是严格的默认设置)。我认为这是不对的。
包
我希望Deno具有所有Express功能,这样就不用任何框架了。但Deno并没有这样做,而是引入了那个Oak框架(“Oak”是它的名字):
https://deno.land/x/oak
为了记录日志,我们需要再导入一个包:
https://deno.land/x/deno_structured_logging
为了其他一些简单的开发功能——我们需要越来越多的包:
https://deno.land/x/
奇怪的是,Deno默认(“开箱即用”)几乎没有集成其中的任何功能,要知道它的使用场景是非常清晰的。至少应该集成最基本的功能,例如路由、日志记录和调试吧。
安全策略
Deno的安全策略仅适用于相对较小的应用程序。大型企业应用程序需要大量权限,因此在我看来,我们必须为每个软件包指定策略。这就是为什么我们需要一个带有包的根文件或生成器(用于单体应用、服务等)的原因所在。使用现在的方法时,如果一个包被感染,并且在应用级别为另一个包提供了权限(所以被感染的程序包将具有该权限),那么整个应用的这个权限都会失效。
deno run --allow-net .\main.ts