分享写了个deno 的demo,说说我的看法

发布于 5 个月前0913

5月的某个普通的一天,deno 1.0发布了。于是利用业余时间写了一个服务端的程序。 GIT:https://github.com/shinku/deno-demo koa 之于 node,相当于oak就之于deno了。 虽然是奇怪的设定,不过仅仅换了个字母顺序而已,koa 和 oak 就是一个同父异母的双胞胎呀。

router
  .get("/", (context) => {
    context.response.body = "Hello world!";
  })

以及

app.use((ctx) => {
// Will throw a 500 on every request.
  ctx.throw(500);
});

koa 与oak有着几乎一致的kpi,所以对于有node经验的开发人员来说,是非常友好的。 我尝试着用deno 写了一个静态资源服务器。koa中有个koa-static可以直接使用,但是oak中还缺乏这个包,所以即便他们长得相似,积累上的差距还是挺多的。

想到这里,万一后期阿里的egg换了deno运行时,会不会改名叫:geg 我索性利用了oak 的洋葱模型的原理,简单写了一个static的oak中间件。

定义一个中间件的基本方式:

export default async (context:any,next:Function)=>{
//塞点内容进来
}

根据文件请求路径去服务器的服务器中访问文件:

const data = Deno.readFileSync(_static+filename);

作为返回主体,设置response的body。

let {response,request} = context;
response.body = data;

然后我再写了一个缓存的模块,将请求资源的路径和data 做个映射,确保在下次访问的时候直接去获取内存中的数据,减少再次读取文件造成的资源开销。 根据文件名分别处理了一下返回的headers的content-type的内容。 以上大致这些内容,我把这个文件放在了并起名为static.ts的文件中

app/utils/static.ts

于是,结合oak的中间件逻辑,监听8000端口(也是koa的中间件逻辑)。

import { Application } from "https://deno.land/x/oak/mod.ts";
import _static from "./utils/static.ts";
const app = new Application();
app.use(_static);
console.log('start at point :8000');
app.listen({ port: 8000 });

运行了deno的启动命令:

deno run --allow-net --allow-read index.ts

项目顺利启动了。当我将文件放在工程里面指定的目录下,用特定的url格式去访问他们的时候,他们如约的出现在了我的浏览器中。

第一次编译的时候,会从denoland上下载ts的代码资源,拉到本地,再在deno的运行时中编译成js文件,提交给V8引擎做最后的编译。所以第一次编译会比较耗时,后期的编译会比较省时间。 TS的编译过程在整个服务的启动之前,也就是说实际上运行过程中完全不用考虑ts的编译问题。所以相比较nodejs,deno的运行效率和node 应该是一摸一样的。

目前没有找到一个类似于pm2 或者supervisor 的进程管理的工具,所以我每次修改service 的代码之后,得反复使用ctrl+C的方式退出当前进程,涉及到端口占用,还得强行运行一次“pkill -9 deno”暴力的关掉deno对于端口的占用,之后再起一次deno的启动命令。整个过程对我身心造成了不小的伤害。

但是我找到了 Deno.watchFs 这个api,可以监听文件目录的变化,同时再作出一定的后续操作;于是我再结合了Deno.run 这个api(类似于nodejs的childprocess.spaw)写了一个能够监听代码变动,并重启服务的服务:launch.ts

const run = ()=>{
     return Deno.run({
        cmd: ["deno", "run","--allow-net","--allow-read","index.ts"],
        cwd:"app",
      });
 }
let _porcess = run();
const watcher = Deno.watchFs("./app");
for await (const event of watcher) {
      console.log('kill proceess');
     _porcess.close();
      console.log('restart');
     _porcess= run();
}

于是我将deno的启动项的代码由

deno run --allow-net --allow-read index.ts

替换成了

deno run --allow-net --allow-read --allow-run launch.ts

这样我再改动app目录下的代码,并需要验证效果的时候就,就会自动重新编译啦。

涉及到的三个allow相关的tag的意义:

--allow-net :允许从远程下载资源,deno 运行时需要拉去远程模块的时候必须

--allow-read:允许调用deno的文件读取的相关权限,deno应用需要访问本地资源的时候必须

--allow-run:允许启用deno.run实现本地命令行调用,deno 中用到各项命令行操作的时候必须

这些allow在一定程度上起到了安全性的作用。 deno 区别于nodejs 对于第三方包的引入方式:

import { Application } from "https://deno.land/x/oak/mod.ts";

这种代码让我对于包管理的方式缺乏安全感,不像 rust开发一样有个cargo.toml 可以统一管理所以调用的第三方包。于是我将第三方包都写在了lib下一个专门的ts去管理

import * as oak from 'https://deno.land/x/oak/mod.ts';
export {
    oak
}

这个文件也可以作为后续管理其他所有第三方包的入口,其他业务模块需要用到这些第三方模块的时候都通过import 这个本地的入口,多少给了我一些安全感。

作为学不动的一方,以下是我在使用deno后的一些感想。。。。

1.没有了node_modules的存在,整个项目代码结构看起来舒服不少。

2.typescript 的全方位支持也让开发过程的体验有了质的飞跃,这代表着我们不用再去顾及typescript 的编译过程,和杂七杂八的webpack的配置项和插件;

3.没有非常有效的包管理工具,使得使用过程中对第三方模块的使用无法直视,缺少安全感,于是要尝试自己去写一些模块管理这些模块;

4.deno最终是由rust 编写,但是最后并没有沿用cargo的那一套非常友好又标准的包管理机制和运行时监听工具,所以目前调试过程还是比较繁琐;

5.目前还没有一个有效的类似于pm2的进程管理工具,意味着如果我要上一个deno的项目,我得先在服务器上装个docker?

6.官方在标准库上还缺乏更多的布局,所以会觉得相对于普通开发者来说现在,还不适合使用deno开发生产业务

由于才刚刚发布的版本,和nodejs 比较生态肯定是不公平的,至少在开发体验上来说,像是轻装上阵,倒是轻松了不少。相比较于node目前的规模,deno并没有解决什么特别大痛点:node_modules包的存在可以说有利有弊吧,ts的编译可以通过webpack搭建实现;deno的运行加了些权限限制,相比较于node来说业务的安全性得到了一定的保障。

以上是来我自己的公众号的搬运,如果大家不嫌弃,欢迎你们关注我的公众号“欣仔互动”哈。 alt

登录后发表评论!
通过Github登录