Anthony Giniers
@antogyn
@aginiers
Laissez tomber Express : passez à son successeur Koa
#DevoxxFR
"Koa is superior to Express in my opinion, having written them both"
- TJ Holowaychuk
"Koa is a pretty large departure from what people know about Express, the design is fundamentally much different, so the migration from Express 3.0 to this Express 4.0 would effectively mean rewriting the entire application, so we thought it would be more appropriate to create a new library."
- koajs GitHub
Express :
app.use(function (req, res, next){
var start = Date.now();
next();
console.log(Date.now() - start);
});
app.use(function (req, res){
res.send('Hello World');
});
Objectif : répondre "Hello World" et loguer le temps de réponse
app.use(function *(next){
var start = Date.now();
yield next;
console.log(Date.now() - start);
});
app.use(function *(){
this.body = 'Hello World';
});
v1 : basée sur les générateurs
app.use(async (ctx, next) => {
const start = Date.now();
await next();
console.log(Date.now() - start);
});
app.use(ctx => {
ctx.body = 'Hello World';
});
v2 : basée sur async/await
Koa :
Objectif : répondre "Hello World" et loguer le temps de réponse
Nouvel objectif : notifier un service externe, répondre "Hello World" et ajouter le temps de réponse dans un header
app.use(async (ctx, next) => {
const start = Date.now();
await next();
ctx.set('X-Response-Time', Date.now() - start);
});
app.use(async (ctx) => {
await notifyService();
ctx.body = 'Hello World';
});
Koa :
X-Response-Time: 50
app.use(async (ctx, next) => {
const start = Date.now();
await next();
ctx.set('X-Response-Time', Date.now() - start);
});
app.use(async (ctx) => {
await notifyService();
ctx.body = 'Hello World';
});
Nouvel objectif : notifier un service externe, répondre "Hello World" et ajouter le temps de réponse dans un header
app.use((req, res, next) => {
const start = Date.now();
next();
res.set('X-Response-Time', Date.now() - start);
});
app.use((req, res) => {
notifyService(() => {
res.send('Hello World');
});
});
Express :
X-Response-Time: 1 ???
next est utilisé comme une fonction synchrone
Nouvel objectif : notifier un service externe, répondre "Hello World" et ajouter le temps de réponse dans un header
Error: Can't set headers after they are sent.
app.use(async (req, res) => {
const start = Date.now();
await notifyService();
res.send('Hello World');
res.set('X-Response-Time', Date.now() - start);
});
Express v2 :
Express n'est pas fait pour !
https://github.com/expressjs/response-time
Monkey patch de response.writeHead
Express en vrai :
const onHeaders = require('on-headers');
app.use((req, res, next) => {
const start = Date.now();
onHeaders(res, function() {
this.setHeader('X-Response-Time', Date.now() - start);
});
next();
});
app.use(async (req, res) => {
await notifyService();
res.send('Hello World');
});
Express :
app.use((req, res) => {
fs.createReadStream('./dir/does_not_exist').pipe(res);
});
Koa :
app.use(ctx => {
ctx.body = fs.createReadStream('./dir/does_not_exist');
});
404 Not Found
Crash du process Node.js
Koa est plus modulaire, avec un core minimaliste (~1600 lignes)
Requêtes par secondes (higher = better)
Environnement de test :
Questions ?