express
express是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,主要基于 Connect 中间件,并且自身封装了路由、视图处理等功能,
Express 提供了 4 个主要特性:
- 与纯 Node 中使用一个函数处理所有请求的代码不同, Express 则使用“中间件栈”处理流。
- 路由与中间件类似,只有当你通过特定 HTTP 方法访问特定 URL 时才会触发处理函数的调用。
- 对 request 和 response 对象方法进行了拓展。
- 视图模块允许你动态渲染和改变 HTML 内容,并且使用其他语言编写 HTML 。
中间件栈
function myFunMiddleware(request, response, next) {
...
next();
}
express内置中间件
express.json、express.urlencoed、express.static
第三方中间件:
morgan、cookie-parser、body-parser、compression、helmet、connect-ratelimit
路由
var express = require("express");
var path = require("path");
var http = require("http");
var app = express();
// 像之前一样设置静态文件中间件。
// 所有的请求通过这个中间件,如果没有文件被找到的话会继续前进
var publicPath = path.resolve(__dirname, "public");
app.use(express.static(publicPath));
// 当请求根目录的时候被调用
app.get("/", function(request, response) {
response.end("Welcome to my homepage!");
});
// 当请求/about的时候被调用
app.get("/about", function(request, response) {
response.end("Welcome to the about page!");
});
// 当请求/weather的时候被调用
app.get("/weather", function(request, response) {
response.end("The current weather is NICE.");
});
// 前面都不匹配,则路由错误。返回 404 页面
app.use(function(request, response) {
response.statusCode = 404;
response.end("404");
});
http.createServer(app).listen(3000);
复杂路由
// 指定“hello”为路由的固定部分
app.get("/hello/:who", function(request, response) {
// :who 并不是固定住,它表示 URL 中传递过来的名字
response.end("Hello, " + request.params.who + ".");
});
扩展 request 和 response
req.ip,res.status,res.send...
response.redirect("/hello/world");
response.redirect("http://expressjs.com");
response.sendFile("path/to/cool_song.mp3")
// ip黑名单
var EVIL_IP = "123.45.67.89";
app.use(function(request, response, next) {
if (request.ip === EVIL_IP) {
response.status(401).send("Not allowed!");
} else {
next();
}
});
视图
应对动态内容的渲染,社区中出现了大量的 Express 模版引擎,例如: EJS、Handlebars、Pug。
var express = require("express");
var path = require("path");
var app = express();
// 告诉 Express 你的视图存在于一个名为 views 的文件夹中
app.set("views", path.resolve(__dirname, "views"));
// 告诉 Express 你将使用EJS模板引擎
app.set("view engine", "ejs");
app.get("/", function(request, response) {
response.render("index", {
message: "Hey everyone! This is my webpage."
});
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, world!</title>
</head>
<body>
<%= message %>
</body>
</html>
koa
Koa是一个设计非常精简的Web框架,是 Express 原班人马基于 ES7 新特性重新开发的框架。框架本身不含任何中间件,可以使我们根据自身需要去组合一些中间件使用。它结合async/await实现了洋葱模式。
路由
const Koa = require('koa')
const route = require('koa-route')
const app = new Koa()
app.use(route.get('/', async (ctx) => {
ctx.body = 'Hello Koa'
}))
app.listen(3000)
视图
const Koa = require('koa')
const route = require('koa-route')
const views = require('koa-views')
const app = new Koa()
app.use(views(path.join(__dirname, './views'), {
extension: 'pug'
}))
app.use(route.get('/', async (ctx) => {
await ctx.render('index', {
title: 'Koa'
})
}))
koa vs express
异常处理
Express 使用 Node 约定的 "error-first 回调" 处理异常,并通过中间件传播。
Koa 通过同步方式编写异步代码,可以通过 try catch
处理异常,非常自然。
// Express
app.use(function (err, req, res, next) {
res.status(err.status || 500).send('error')
})
// Koa
app.use(async (ctx, next) => {
try {
await next()
} catch (err) {
ctx.app.emit('error', err)
ctx.status = err.status || 500
ctx.body = { message: err.message }
}
})
Context
Koa 新增了一个 Context 对象,用来代替 Express 中的 Request 和 Response,作为请求的上下文对象。 Context 上除了 Request 和 Response 两个对象之外,还有 Node.js 原生提供的 req 、res、socket 等对象。
中间件模型
express使用的connect中间件模型
const connect = require('connect')
const app = connect()
app.use(function m1 (req, res, next) {
console.log('m1')
next()
console.log('m1 end')
})
app.use(function m2 (req, res, next) {
console.log('m2')
next()
console.log('m2 end')
})
app.use(function m3 (req, res, next) {
console.log('m3')
res.end('hello')
})
app.listen(8080)
/*
m1
m2
m3
m2 end
m1 end
*/
connect的简化模型
http.createServer(function (req, res) {
console.log('m1')
m1 (req, res) {
console.log('m2')
m2 (req, res) {
m3 (req, res) {
console.log('m3')
res.end('hello')
}
}
console.log('m2 end')
}
console.log('m1 end')
})
koa的洋葱圈模型
const Koa = require('koa')
const app = new Koa()
app.use(async function m1 (ctx, next) {
console.log('m1')
await next()
console.log('m1 end')
})
app.use(async function m2 (ctx, next) {
console.log('m2')
await next()
console.log('m2 end')
})
app.use(async function m3 (ctx) {
console.log('m3')
ctx.body = 'hello'
})
app.listen(8080)
//输出与connect模型一致
koa简化模型
Promise.resolve(async m1 () {
console.log(m1)
await Promise.resolve(async m2 () {
console.log(m2)
await Promise.resolve(async m3 () {
console.log(m3)
ctx.body = 'xxx'
})
console.log(m2 end)
})
console.log(m1 end)
})
egg
egg.js是阿里旗下基于node.js和koa是一个node企业级应用开发框架,可以帮助开发团队,和开发人员减少成本。 基于koa2、es6、es7使得node具有更有规范的开发模式,更低的学习成本、更优雅的代码、更少的维护成本。