Anthony Giniers

@antogyn

@aginiers

Laissez tomber Express : passez à son successeur Koa

#DevoxxFR

Express.js

  • Framework web Node.js
    • Routing
    • Middlewares (basés sur Connect)
    • Hautes performances
    • ...
  • v1 sortie en 2010
  • Le E de MEAN
  • Créé par TJ Holowaychuk (ejs, commander, co, ...)

Koa.js

  • Framework web Node.js
  • en v1 : middlewares basés sur des générateurs
  • en v2 : middlewares basés sur async/await (2017)
  • Créé par TJ Holowaychuk en 2013/2014​

"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 vs Koa : middlewares

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');
});

  • Callback synchrone (next)
  • Envoi de la réponse dans un middleware (res.send)

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 :

  • Callback asynchrone (next)
  • Utilisation d'un contexte plutôt que d'envoyer directement la réponse

Express vs Koa : middlewares

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 :

Express vs Koa : middlewares

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

Express vs Koa : middlewares

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

Express vs Koa : middlewares

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

Express vs Koa : middlewares

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 vs Koa : streams

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

Express vs Koa : features

Koa est plus modulaire, avec un core minimaliste (~1600 lignes)

  • koa-router
  • koa-ejs, koa-pug, ...
  • koa-send
  • koa-jsonp
  • ...

Express vs Koa : performances

  • Performances comparables mais léger avantage à Koa

Requêtes par secondes (higher = better)

Environnement de test :

  • 32 GB RAM, i7-4790 CPU
  • VM à 20$ sur Digital Ocean

 

Express vs Koa : communauté

Express vs Koa : communauté

  • Koa est populaire mais est moins utilisé qu'Express
  • ... du coup, moins de middlewares
  • Il existe un module pour pouvoir utiliser les middlewares Express (mais il ne peut forcément pas marcher pour tous) 
  • La quasi intégralité des libs qui s'utilisent par middleware ont une version Koa

Récap

  • Flux de contrôle basé sur les promesses avec async/await
    • "pile" de middlewares asynchrones
  • Abstraction au-dessus de req/res du module http (context)
    • possibilité de changer la réponse à tout moment
    • meilleure gestion des streams
    • évite de polluer req/res
  • Léger et modulaire

Merci !

Questions ?

Laissez tomber Express : passez à son successeur Koa

By antogyn

Laissez tomber Express : passez à son successeur Koa

  • 846