前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初探Deno.js

初探Deno.js

原创
作者头像
杜逸先
修改2021-06-10 11:51:16
6620
修改2021-06-10 11:51:16
举报

Node.js 的作者 Ryan Dahl 在 2018 年 JSConf EU 上发布了一篇演讲:10 Things I Regret About Node.js,讲述了 他认为自己在设计 Node.js 时的十个(实际上演讲中只提到七个)失误,包括:没有坚持使用 Promise,使用了 GYP 构建系统,package.json 和 node_modules 的设计失 误等。

在演讲中 Ryan Dahl 宣布了一个新项目:Deno,一个新的服务端 Javascript 运行时。经过两年多的发展,Deno 已经发布了 1.8 版本,也有了一个活跃的开发者社区。我们今天就来简单的了解一下 Deno。

Deno 简介

Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust.

Deno 使用 V8 引擎,由 Rust 构建,是一个简单、现代、安全的 Javascript 和 Typescript 运行时。

Deno 的主要特性有:

  • 默认安全。外部代码没有文件系统、网络、环境的访问权限,除非显式开启。
  • 支持开箱即用的 TypeScript 的环境。
  • 只分发一个独立的可执行文件 (deno)。
  • 有着内建的工具箱,比如一个依赖信息查看器 (deno info) 和一个代码格式化工具 (deno fmt)。
  • 有一组经过审计的标准模块,保证能在 Deno 上工作。
  • 脚本代码能被打包为一个单独的 JavaScript 文件。

<!-- more -->

安装 Deno

可以执行快速安装脚本方便地将 Deno 安装到不同操作系统上。

Mac 和 Linux 平台

代码语言:txt
复制
curl -fsSL https://deno.land/x/install/install.sh | sh

Windows 平台(使用 Powershell)

代码语言:txt
复制
iwr https://deno.land/x/install/install.ps1 -useb | iex

第一个 Deno 脚本

安装好 Deno 后,我们就可以直接在终端里使用 Deno 运行 Javascript/Typescript 脚本。

代码语言:txt
复制
$ deno run https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using latest version (0.91.0) for http://deno.land/std/examples/welcome.ts
Download https://deno.land/std@0.91.0/examples/welcome.ts
Check https://deno.land/std/examples/welcome.ts
Welcome to Deno!

有例子中我们可以知道deno run可以直接运行远程脚本,当然运行本地脚本也不是问题。

代码语言:txt
复制
$ echo 'console.log("Hello, World!")' > hello.ts
$ deno run .\hello.ts
Check file:///C:/Users/duyix/lab/deno-code/hello.ts
Hello, World!

使用 Deno 运行 HTTP Server

我们再运行一下 Deno 官网示例中的启动 HTTP Server 的程序。

代码语言:txt
复制
import { serve } from "https://deno.land/std@0.90.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" });
}
代码语言:txt
复制
$ deno run .\server.ts
Download https://deno.land/std@0.90.0/http/server.ts
# 省略了一些依赖下载的日志
Check file:///C:/Users/duyix/lab/deno-code/server.ts
error: Uncaught PermissionDenied: network access to "0.0.0.0:8000", run again with the --allow-net flag
    at processResponse (core.js:223:11)
    at Object.jsonOpSync (core.js:246:12)
    at opListen (deno:cli/rt/30_net.js:32:17)
    at Object.listen (deno:cli/rt/30_net.js:207:17)
    at serve (server.ts:304:25)
    at server.ts:2:11

可以看到直接运行server.ts会失败,Deno 报错PermissionDenied。这是 Deno 默认的安全策略的行为,使用 Deno 运行脚本时默认不提供网络连接、文件 IO 等权限,需要显式的在deno run命令中启用对应的权限,在这个例子中我们需要加上--allow-net标志来启用网络权限。

代码语言:txt
复制
$ deno run --allow-net .\server.ts
http://localhost:8000/

然后我们就可以访问本地的 8000 端口了。

代码语言:txt
复制
$ http :8000
HTTP/1.1 200 OK
content-length: 12

Hello World

Deno REPL

和 Node 类似,Deno 也有 REPL 模式,直接运行deno repdeno就可以交互式地运行 JavaScript 脚本了,Deno 的 REPL 模式暂时还不提供 Typescript 支持。

代码语言:txt
复制
$ deno
Deno 1.5.4
exit using ctrl+d or close()
> let resp = await fetch('https://httpbin.org/headers')
undefined
> await resp.json()
{
  headers: {
    Accept: "*/*",
    "Accept-Encoding": "gzip, br",
    Host: "httpbin.org",
    "User-Agent": "Deno/1.5.4",
    "X-Amzn-Trace-Id": "Root=1-6058b379-7fd616e829aa462029478558"
  }
}
> close()

我们在 Deno REPL 中使用了 fetch 进行网络请求,Deno 实现了一些常见的Web API。并且可以看到在 REPL 模式中,deno 默认开启了网络权限。

使用 Deno 编写命令行程序

Deno 是编写命令行工具的一个新的选择。

代码语言:txt
复制
// dn-echo.ts
console.log(Deno.args.join(" "));
代码语言:txt
复制
$ deno run ./dn-echo.ts 1 2 3
1 2 3

Deno是 Deno 的一个全局对象,提供了一些系统 API(命令行参数获取、文件读写等)。可以通过Deno.arg获取命令行参数。

使用 Deno 编写命令行程序另一个便捷之处是我们可以很方便地通过deno install命令将本地脚本或网络脚本安装成全局工具。

代码语言:txt
复制
$ deno install .\dn-echo.ts
✅ Successfully installed dn-echo
C:\Users\duyix\.deno\bin\dn-echo.cmd

值得注意的是deno install命令也要加上对应的权限选项。

代码语言:txt
复制
$ deno install -n dn-cat --allow-read https://deno.land/std@0.90.0/examples/cat.ts
Download https://deno.land/std@0.90.0/examples/cat.ts
Check https://deno.land/std@0.90.0/examples/cat.ts
✅ Successfully installed dn-cat
C:\Users\duyix\.deno\bin\dn-cat.cmd
C:\Users\duyix\.deno\bin\dn-cat (shell)

$ dn-cat .\hello.ts
console.log("Hello, World!")

我们从 url 安装了一个命令行脚本 cat(使用-n dn-cat选项指定了全局工具的名字),并且加上了--allow-read选项来开启读文件权限。

使用 Deno 开发 Web 应用

作为 Node.js 的挑战者,开发 Web 应用自然是 Deno 的看家本领。Deno 标准库http模块的功能已经很齐全了。不过为了更佳的开发体验,我们在这里使用oak框架(借鉴了 Node.js 中的 koa 框架)来开发 web 应用。

代码语言:txt
复制
//app.js
import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const app = new Application();

const port = 8000;

// Logger
app.use(async (ctx, next) => {
  await next();
  const rt = ctx.response.headers.get("X-Response-Time");
  console.log(`HTTP ${ctx.request.method} on ${ctx.request.url}`);
  console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`);
});

// Timing
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.response.headers.set("X-Response-Time", `${ms}ms`);
});

const router = new Router();

router
  .get("/", (ctx) => {
    ctx.response.body = "Hello Deno";
  })
  .get("/:name", (ctx) => {
    ctx.response.body = `Hello ${ctx.params.name}`;
  });

app.use(router.routes());
app.use(router.allowedMethods());

app.addEventListener("listen", () => {
  console.log(`Listening on localhost:${port}`);
});

await app.listen({ port });

app.js中,我们初始化了一个Application对象app,注册了两个中间件(分别用来打日志和记录请求时间)。

然后使用oak框架提供的Router组件实例化了一个router对象,定义了两个接口并将router注册到了app上。

随后在app上注册了一个事件监听,在listen事件发生(也就是应用开始运行)时,输出了相关日志。

我们可以直接运行app.js

代码语言:txt
复制
$ deno run --allow-net ./app.js
Listening on localhost:8000

随后就可以访问接口了。

代码语言:txt
复制
$ http :8000/
HTTP/1.1 200 OK
content-length: 10
content-type: text/plain; charset=utf-8
x-response-time: 1ms

Hello Deno

$ http :8000/mike
HTTP/1.1 200 OK
content-length: 10
content-type: text/plain; charset=utf-8
x-response-time: 0ms

Hello mike

部署 Deno Web 应用

第一次运行app.js的时候 Deno 需要从互联网上下载其相关依赖, 我们可以使用deno cache命令手动将指定脚本的依赖缓存到本地(使用-r选项可以强制重新加载)。

代码语言:txt
复制
$ deno cache -r ./app.js

deno cache命令在构建镜像时还是很必要的,因为无法保证容器在每次运行的时候都可以顺利下载好依赖。直接在构建阶段将依赖准备好是一个更稳妥的选择。

一个常见的 Deno Web 应用的 Dockerfile 如下:

代码语言:txt
复制
FROM hayd/alpine-deno:1.8.2

# The port that your application listens to.
EXPOSE 1993

WORKDIR /app

# Prefer not to run as root.
USER deno

# Cache the dependencies as a layer (the following two steps are re-run only when deps.ts is modified).
# Ideally cache deps.ts will download and compile _all_ external files used in main.ts.
COPY deps.ts .
RUN deno cache deps.ts

# These steps will be re-run upon each file change in your working directory:
ADD . .
# Compile the main app so that it doesn't need to be compiled each startup/entry.
RUN deno cache main.ts

CMD ["run", "--allow-net", "main.ts"]

打包脚本

Deno CLI 提供deno bundle命令可以将指定脚本及其依赖打包成一个 javascript 文件(类似 webpack),提供了另外一种分发应用的方式。

代码语言:txt
复制
$ deno bundle ./app.js app.bundle.js
Bundle file:///C:/Users/duyix/lab/deno-code/app.js
Check file:///C:/Users/duyix/lab/deno-code/app.js
Emit "app.bundle.js" (402.67KB)

可以看到打包生成的脚本还是很大的,不过根据我的观察app.bundle.js其实是格式化良好的,并且里面的函数名和参数名等都没有缩减过。deno bundle的输出文件大小精剪还是有很大优化空间的。

我个人还是更推荐使用容器镜像运行 Deno 应用,更规范,也更容易维护应用源代码和依赖。

总结

Deno 毕竟还是一个很年轻的项目,稳定性和配套的资源和支持与 Node.js 相比还是有很大差距的。但正如 Ryan Dahl 所说,Node.js 有其固有的一些历史遗留的设计问题 。Deno 的优秀理念正在吸引越来越多的开发者使用并加入社区,相信 Deno 会成为服务端 Web 开发领域的新秀。

原文(https://cloud.tencent.com/developer/article/2263920

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Deno 简介
  • 安装 Deno
  • 第一个 Deno 脚本
  • 使用 Deno 运行 HTTP Server
  • Deno REPL
  • 使用 Deno 编写命令行程序
  • 使用 Deno 开发 Web 应用
    • 部署 Deno Web 应用
      • 打包脚本
      • 总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档