deno 从诞生,到如今有本身的标准库,以及一些第三方库,让我对deno在web的应用有了必定的兴趣,html
我知道deno还没有成熟,可是恰好最近心闲下来了,就找点事作作,做为一个前端,我也期待经过这个机会了解更多的一些后台的事情。前端
若是你能在看到文章以后,给我提出一些建议我将不胜感激~java
若是你也想一块儿开发,我也很是欢迎~node
阅读大约须要 4 - 5 分钟git
基于deno v0.3.0,Github:https://github.com/fen-land/deno-fengithub
Fen 是一个使用Typescript基于deno的轻量级web框架,他经过Server主体来实现服务,经过Process以及Tool来赋予Server各类各样的功能。web
Fen 仅仅经过上下问context来链接各个环节,虽然这样的模式存在着上下文在修改过程当中难以保证稳定的问题,可是若是Process和Tool的开发遵照一些基本原则,仍是能基本维持context的稳定的。同时虽然 Fen 经过Process以及Tool来赋能,可是其自己仍是进行了必定的封装以及进行了一些操做来让使用更加便捷。typescript
由于其实没有提出很新的想法,因此仍是使用了不少以前在java或者node中用过的后台的用法,若是你们以为有怎样的新想法,也欢迎你们提issue。json
首先,若是你不知道deno,快去看看吧: https://deno.land/浏览器
你须要安装最新的deno:
curl -fsSL https://deno.land/x/install/install.sh | sh
复制代码
而后,你须要写你的第一个Fen的文件
// hello.ts
import { Server } from "https://raw.githubusercontent.com/fen-land/deno-fen/master/src/server.ts";
const s = new Server();
s.port = 8882;
s.start();
复制代码
由于deno尚未相应成熟的包管理(也可能不会有)这里引用文件还暂时是经过github来作一个托管,以后会完善一下,有更好的地址使用方式。
最后你须要运行这个文件
deno -A hello.ts
复制代码
在浏览器中访问:http://127.0.0.1:8882 你将会看到:
You have success build a server with fen on 0.0.0.0:1882
Try set controller using setController method,
Or try our route tool :)
复制代码
这就是你的第一个 Fen 服务器。
Context是Fen的核心概念,他起到了一个在生命周期里面传递的做用,也是controller进行操做的手段。
结构以下:
{
// ---- 这些变量都取自http派发都ServerRequest
url,
method,
proto,
headers,
conn,
reader,
writer,
// ----
request,
path, // 不带有参数的路径
params, // Map<string, string> url里面获得的参数
data: new Map<string, any>(),
body: "",// respond 返回的body
status: 200,// 状态码
config: {
disableRespond: false, // 禁用fen自带的respond流程
disableBodyEncode: false, // 禁止按照类型来encode body的流程
disableContentType: false, // 禁止根据config来设置header
mimeType: "text/plain", // 返回结果的mimeType
charset: "utf-8" // 返回结果的Type
},
reqBody, // 尝试解码后的请求的body
originBody, // 本来请求的body
logger // tool 中带有的Logger
};
复制代码
经过使用context,你能够经过简单的赋值来决定响应:
s.setController(async ctx => {
ctx.config.mimeType = "application/json";
ctx.body = {
now: "you",
can: ["see"],
me: 2
};
});
复制代码
Process一般运行在controller前,为context赋能,使其拥有特定的功能,Process经过addProcess
方法来进行添加。
Session是现有的惟一Process,他为context加入了session
这样一个键,这样就赋予了controller了web session的能力。
import {Server} from 'https://raw.githubusercontent.com/fen-land/deno-fen/raw/master/src/server.ts';
import Session from 'https://raw.githubusercontent.com/fen-land/deno-fen/raw/master/src/process/session.ts'
const session = new Session();
const s = new Server();
// session 加入的仅仅是session的process
s.addProcess(session.process);
s.port = 1882;
s.setController(
async (ctx) => {
// session 是一个 Map<string, any>()
const {session} = ctx;
let c = session.get('c') || 1;
if(ctx.path === '/') {
session.set('c', c + 1);
}
ctx.body = `It\'s alive for path '/' ${c} times in this browser!`;
}
);
s.start();
复制代码
Fen要实现不少基本的功能相似于静态文件,路由之类的,须要使用Tool,而且在Server中也使用了一些Tool。
Fen 本身有一个log系统,虽然是很简陋的那种,可是能够帮助开发时候获得更多信息,你能够在Server或者context中找到它。log是按照级别来提供的,你能够在开发中使用logger.debug('debug')
这样的方式来产出log,低于设置level的log都不会产出。
'ALL': 全部log都输出,
'TRACE',
'DEBUG',
'INFO',
'WARN',
'ERROR',
'FATAL',
'OFF': 禁止全部log
复制代码
你能够经过 changeLevel
来改变level:
logger.changeLevel('ALL');
复制代码
Static 为 Server提供了静态代理的功能,
import {Server} from 'https://raw.githubusercontent.com/fen-land/deno-fen/raw/master/src/server.ts';
import {staticProcess} from "https://raw.githubusercontent.com/fen-land/deno-fen/raw/master/src/tool/static.ts";
const s = new Server();
s.port = 1882;
// it will respond file from the path where deno run
s.setController(staticProcess({root: ''}));
s.start();
复制代码
static提供了一些额外的option:
{
root: root path of the file,
maxAge: (s),
allowHidden: allow access hidden file,
index: access if no file name provide 'index.html',
immutable: immutable in cache-control,
pathRender: (path) => afterpath, if you want do sth. with path
};
复制代码
咱们为Fen 也提供了路由Tool,他有很灵活的使用方法,你也能够经过使用多个Router来进行开发,最后把他们merge到同一个上,下面展现了大部分可使用的路由方法的例子。
import { Server } from "https://raw.githubusercontent.com/fen-land/deno-fen/raw/master/src/server.ts";
import { Router } from "https://raw.githubusercontent.com/fen-land/deno-fen/raw/master/src/tool/router.ts";
const s = new Server();
s.port = 1882;
s.logger.changeLevel('ALL');
let mergeRouter = new Router('merge');
mergeRouter
.get('/', async (ctx) => ctx.body = `${ctx.router.name} in ${ctx.router.route}`)
.post('/', async (ctx) => ctx.body = `POST ${ctx.router.name} in ${ctx.router.route}`)
.get('me', async (ctx) => ctx.body = `${ctx.router.name} in ${ctx.router.route}`);
let router = new Router();
router
.get('/:id', async (ctx) => {
ctx.body = `we have ${JSON.stringify(ctx.router.params)} in ${ctx.router.route}`
})
.get('/:id/:name', async (ctx) => {
ctx.body = `we have ${JSON.stringify(ctx.router.params)} in ${ctx.router.route}`
})
.get('/hello/:name', async (ctx) => {
ctx.body = `hello ${ctx.router.params.name} in ${ctx.router.route}`
})
.use({ '/use': {get: async (ctx) => ctx.body = `use in ${ctx.router.route}`}})
.merge('/merge', mergeRouter);
;
s.setController(router.controller);
s.start();
复制代码
Router
有如下的方法:
use(route: IRoute) // 一种区别于下面方法的直接批量添加路由的方式
// IRoute 结构:
// {[path]: {[method]: async function controller(cxt)}}
merge(route: string, router:Router) // 你甚至能够经过路径前缀来合并Router们
get
post
head
put
delete
connect
options
trace
复制代码
接下来Fen的开发计划是:
(其实也存在我被毕业设计压榨后到答辩前没法完成的状况)XD