What is Polka ?
Polka is an extremely minimal, highly performant Express.js alternative.
Installation.
npm i --save polka
Usage
Polka has similar patterns with ExpressJS in terms of routing and API calls.
Simple Example.
const polka = require('polka');
polka()
  .get('/', (req, res) => {
      res.end('Hello there !');
  })
  .listen(9000).then(_ => {
    console.log(`> Running on localhost:3000`);
  });
Polka's API
Polka has four (4) main API methods.
- Polka(options) - Returns an instance of polka.
- use(base, ..fn)
- parse(req)
- listen(port, hostname)
- handler(req, res, parsed)
Routing with Polka.
Routes are used to define how an application responds to varying HTTP methods and endpoints.
Basics
Each route is comprised of a path pattern, a HTTP method, and a handler (aka, what you want to do).
In code, this looks like:
app.METHOD(pattern, handler);
wherein:
- 
appis an instance ofpolka*methodis any valid HTTP method, lowercased
- 
patternis a routing pattern (string)
- 
handleris the function to execute whenpatternis matched
Also, a single pathname (or pattern) may be reused with multiple METHODs.
The following example demonstrates some simple routes.
const app = polka();
app.get('/', (req, res) => {
  res.end('Hello world!');
});
app.get('/users', (req, res) => {
  res.end('Get all users!');
});
app.post('/users', (req, res) => {
  res.end('Create a new User!');
});
app.put('/users/:id', (req, res) => {
  res.end(`Update User with ID of ${req.params.id}`);
});
app.delete('/users/:id', (req, res) => {
  res.end(`CY@ User ${req.params.id}!`);
});
Patterns
Unlike the very popular path-to-regexp, Polka uses string comparison to locate route matches. While faster & more memory efficient, this does also prevent complex pattern matching.
However, have no fear! 💥 All the basic and most commonly used patterns are supported. You probably only ever used these patterns in the first place. 😉
See
comparisonfor the list ofRegExp-based patterns that Polka does not support.
The supported pattern types are:
- static (/users)
- named parameters (/users/:id)
- nested parameters (/users/:id/books/:title)
- optional parameters (/users/:id?/books/:title?)
- any match / wildcards (/users/*)
Parameters
Any named parameters included within your route pattern will be automatically added to your incoming req object. All parameters will be found within req.params under the same name they were given.
Important: Your parameter names should be unique, as shared names will overwrite each other!
app.get('/users/:id/books/:title', (req, res) => {
  let { id, title } = req.params;
  res.end(`User: ${id} && Book: ${title}`);
});
$ curl /users/123/books/Narnia
#=> User: 123 && Book: Narnia
Methods
Any valid HTTP method is supported! However, only the most common methods are used throughout this documentation for demo purposes.
Note: For a full list of valid METHODs, please see this list.
Handlers
Request handlers accept the incoming ClientRequest and the formulating ServerResponse.
Every route definition must contain a valid handler function, or else an error will be thrown at runtime.
Important: You must always terminate a
ServerResponse!
It's a very good practice to always terminate your response (res.end) inside a handler, even if you expect a middleware to do it for you. In the event a response is/was not terminated, the server will hang & eventually exit with a TIMEOUT error.
Note: This is a native
httpbehavior.
Async Handlers
If using Node 7.4 or later, you may leverage native async and await syntax! 😻
No special preparation is needed — simply add the appropriate keywords.
const app = polka();
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function authenticate(req, res, next) {
  let token = req.getHeader('authorization');
  if (!token) return app.send(res, 401);
  req.user = await Users.find(token); // <== fake
  next(); // done, woot!
}
app
  .use(authenticate)
  .get('/', async (req, res) => {
    // log middleware's findings
    console.log('~> current user', req.user);
    // force sleep, because we can~!
    await sleep(500);
    // send greeting
    res.end(`Hello, ${req.user.name}`);
  });
Middleware
Middleware are functions that run in between (hence "middle") receiving the request & executing your route's handler response.
Coming from Express? Use any middleware you already know & love! 🎉
The middleware signature receives the request (req), the response (res), and a callback (next).
These can apply mutations to the req and res objects, and unlike Express, have access to req.params, req.pathname, req.search, and req.query!
Most importantly, a middleware must either call next() or terminate the response (res.end). Failure to do this will result in a never-ending response, which will eventually crash the http.Server.
// Log every request
function logger(req, res, next) {
  console.log(`~> Received ${req.method} on ${req.url}`);
  next(); // move on
}
function authorize(req, res, next) {
  // mutate req; available later
  req.token = req.getHeader('authorization');
  req.token ? next() : ((res.statusCode=401) && res.end('No token!'));
}
polka().use(logger, authorize).get('*', (req, res) => {
  console.log(`~> user token: ${req.token}`);
  res.end('Hello, valid user');
});
$ curl /
# ~> Received GET on /
#=> (401) No token!
$ curl -H "authorization: secret" /foobar
# ~> Received GET on /foobar
# ~> user token: secret
#=> (200) Hello, valid user
In Polka, middleware functions are mounted globally, which means that they'll run on every request. Instead, you'll have to apply internal filters to determine when & where your middleware should run.
Note: This might change in Polka 1.0 🤔
function foobar(req, res, next) {
  if (req.pathname.startsWith('/users')) {
    // do something magical
  }
  next();
}
Middleware Errors
If an error arises within a middleware, the loop will be exited. This means that no other middleware will execute & neither will the route handler.
Similarly, regardless of statusCode, an early response termination will also exit the loop & prevent the route handler from running.
There are three ways to "throw" an error from within a middleware function.
Hint: None of them use
throw
- 
*Pass any string to next()*This will exit the loop & send a 500status code, with your error string as the response body.
 
    polka()
      .use((req, res, next) => next('💩'))
      .get('*', (req, res) => res.end('wont run'));
    $ curl /
    #=> (500) 
- 
Pass an Errortonext()This is similar to the above option, but gives you a window in changing the statusCodeto something other than the500default.
 
function oopsies(req, res, next) {
  let err = new Error('Try again');
  err.code = 422;
  next(err);
}
    $ curl /
    #=> (422) Try again
- 
Terminate the response early Once the response has been ended, there's no reason to continue the loop! This approach is the most versatile as it allows to control every aspect of the outgoing res.
 
    function oopsies(req, res, next) {
      if (true) {
        // something bad happened~
        res.writeHead(400, {
          'Content-Type': 'application/json',
          'X-Error-Code': 'Please dont do this IRL'
        });
        let json = JSON.stringify({ error:'Missing CSRF token' });
        res.end(json);
      } else {
        next(); // never called FYI
      }
    }
$ curl /
    #=> (400) {"error":"Missing CSRF token"}
Benchmarks
A round of Polka-vs-Express benchmarks across varying Node versions can be found here.
Important: Time is mostly spent in your application code rather than Express or Polka code! Switching from Express to Polka will (likely) not show such drastic performance gains.
Node 8.9.0
Native
    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     2.24ms  112.34us   5.57ms   92.15%
        Req/Sec     5.38k    99.48     5.57k    81.81%
      432562 requests in 10.10s, 42.90MB read
    Requests/sec:  42815.14
    Transfer/sec:      4.25MB
Polka
    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     2.26ms  115.55us   5.19ms   87.16%
        Req/Sec     5.32k    97.34     5.55k    72.77%
      428208 requests in 10.10s, 42.47MB read
    Requests/sec:  42388.92
    Transfer/sec:      4.20MB
Express
    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     5.15ms  421.69us   8.51ms   77.95%
        Req/Sec     2.34k    77.06     2.55k    72.12%
      186390 requests in 10.01s, 36.97MB read
    Requests/sec:  18628.36
    Transfer/sec:      3.70MB
Fastify
    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     2.91ms  201.13us   7.51ms   58.07%
        Req/Sec     4.14k   130.04     4.48k    65.59%
      333158 requests in 10.10s, 41.30MB read
    Requests/sec:  32979.84
    Transfer/sec:      4.09MB
Koa
    Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     3.43ms  369.96us   8.67ms   87.30%
        Req/Sec     3.51k   114.78     4.12k    69.76%
      281808 requests in 10.10s, 38.97MB read
    Requests/sec:  27892.99
    Transfer/sec:      3.86MB
Comparisons
Polka's API aims to be very similar to Express since most Node.js developers are already familiar with it. If you know Express, you already know Polka! 💃
There are, however, a few main differences. Polka does not support or offer:
1) Any built-in view/rendering engines.
Most templating engines can be incorporated into middleware functions or used directly within a route handler.
2) The ability to throw from within middleware.
However, all other forms of middleware-errors are supported.( see middleware options)
    function middleware(res, res, next) {
  // pass an error message to next()
  next('uh oh');
  // pass an Error to next()
  next(new Error('🙀'));
  // send an early, customized error response
  res.statusCode = 401;
  res.end('Who are you?');
}
3) Express-like response helpers... yet! (#14)
Express has a nice set of response helpers. While Polka relies on the native Node.js response methods, it would be very easy/possible to attach a global middleware that contained a similar set of helpers. (TODO)
4) RegExp-based route patterns.
Polka's router uses string comparison to match paths against patterns. It's a lot quicker & more efficient.
The following routing patterns are not supported:
app.get('/ab?cd', _ => {});
app.get('/ab+cd', _ => {});
app.get('/ab*cd', _ => {});
app.get('/ab(cd)?e', _ => {});
app.get(/a/, _ => {});
app.get(/.*fly$/, _ => {});
The following routing patterns are supported:
    app.get('/users', _ => {});
    app.get('/users/:id', _ => {});
    app.get('/users/:id?', _ => {});
    app.get('/users/:id/books/:title', _ => {});
    app.get('/users/*', _ => {});
Credits.
All credits goes to Luke Edwards for his awesome works.
 


 
    
Top comments (4)
However, have no fear! 💥
Seems to me like a 1:1-copy of the Readme of the repository, therefore also the emojis like in GitHub.
Oh Yeah ! Silly me
Great! Thanks