Koa has been released for nearly 6 years. As the biggest dark horse of Node service framework after Express, there are a lot of design ideas worth learning. This article introduces KOA step by step from simple to complex, and is suitable for new veterans to read.

introduce

Here is a quote from the Official Chinese website

Koa is a new Web framework, built by the same people behind Express, that aims to be a smaller, more expressive, and more robust cornerstone of web application and API development. By making use of async functions, Koa helps you discard callback functions and greatly enhances error handling. Koa does not bundle any middleware, but rather provides an elegant way to help you write server-side applications quickly and happily.

By starting a Node HTTP server and listening on a port, we can access our service locally through something like localhost:3000. This service can be a Web site or a restful interface. It could be a static file service and so on.

Hello Word

There is a Hello Word example for any language or framework to represent its simplest introductory Demo, as shown below

At this point, go to the browser localhost:3000 and we’ll see Hello Word printed and a KOA-based service will start.

context

The first step in understanding KOA is to understand the context

For example, someone in your wechat group says it’s snowing outside, but when you go to the window, you see a clear sky. Then you realize that it is also October, and you are in the cold north, while you are in the hot south.

Similarly, a request may contain information such as the user’s login status, or some Token, which is part of the context used to determine the context of the request.

The Koa Context encapsulates node’s request and response objects into a single object and provides many useful methods for developing Web applications and APIs. Operations that are used frequently in HTTP Server development are implemented directly in Koa, rather than in higher-level frameworks, so middleware does not need to duplicate these common functions.

The middleware

Let’s start with an official example:

To clarify, the code initializes an instance of KOA. The following three middleware methods are loaded using the use method, in the order in which they are executed:

  1. Enter the first middleware
  2. next()Move on to the next middleware
  3. new Data()Record the current time
  4. next()Move on to the next middleware
  5. willctx.bodyThe assignment
  6. Go back to the previous middleware to record the current time again and calculate the time difference saved tohttp header
  7. Go back to the previous middleware to headerX-Response-timePrint it out

The order of execution here extends from the classic Onion model

The same middleware goes back and forth twice in the course of a single request, allowing us to process logic at different stages of the request.

The source code parsing

The two most important concepts in KOA are described above. Now let’s analyze how koA works inside koA. How is the so-called Onion model built

The lib directory for koA source code is quite simple.

lib
  |- application.js
  |- context.js
  |- request.js
  |- response.js
Copy the code

The Application class is initialized

The entry file is application.js, which is where we’ll start

This class inherits node Events from the constructor constructor constructor constructor ();

  • Proxy The proxy is disabled by default.
  • The Middleware is an empty array, so be careful here.
  • Env based on the environment variableNODE_ENVTo judge.
  • Context, Request, and Response pass, respectivelyObject.createThe lib method imports the corresponding file in the lib directory tothisThe current context and does not pollute the imported object.

Method of use

In normal coding order, after initializing the koA instance (const app = new koa ()), we need to call app.use() to mount our middleware. So what does the use method do

Check whether the middleware is a function, check whether the middleware is a generator function type, and simply push the middleware functions into the middleware array.

Is there a capital “WHAT” in your mind?

It’s pretty straightforward, it doesn’t have any logic, but as you might have guessed, it loops through the middleware methods. It’s not clear how the Onion model comes from here, so let’s just stick with the code.

Listen method

According to the normal coding sequence, after using our middleware, app.listen(3000)

So what does Listen do

This http.createServer is node’s native method for starting the HTTP service. Extending the basics a bit, this method takes two arguments

  • options[IncomingMessage, ServerResponse]Node v9.6.0 and V8.12.0 are not supported here
  • requestListenerThis parameter is of type function and is passed in on each requestreq, resTwo parameters

The this.callback() method must return a function and take two arguments (req, res)

The amount of information in this callback is a bit large, the code itself is not difficult to understand, and the comments explain it from top to bottom.

Compose method

The compose method is responsible for generating the onion model, which is implemented through the KOA-compose package. The source code is as follows

Fn (context, dispatch.bind(null, I + 1))

This dispatch.bind(null, I + 1) is the second argument we normally write to middleware, next,

We execute this next() method to actually get the next middleware execution,

It is not hard to understand why we await next(). When waiting for the back of all the middleware series execution, looking back at the above middleware part of the execution order suddenly revealed.

CreateContext method

Callback (const CTX = this.createcontext (req, res)

The main thing here is to mount req, res, this.request, this.response into the context. The hierarchy of circular reference is clarified through assignment, which is convenient for users.

HandleRequest method

Callback: This. HandleRequest (CTX, fn)

Take the Onion models generated by CTX and Compose and start consuming middleware one by one.

The context. Js file

Now that the framework is clear, let’s look at the details inside context.js. At the end of the file there are two large sections of the proxy.

Here you can see the entire set of req and RES methods, so which methods are readable, which methods are writable, which methods are both readable and writable, and which methods are not allowed to change

That’s what the delegates library does.

Delegates are internally controlled by the __defineGetter__ and __defineSetter__ methods of reading and writing, of course we can learn thoughts from them but not follow them.

Both apis will give the same warning when searching on the MDN

This feature is deprecated in favor of defining setters using the object initializer syntax or the Object.defineProperty() API.

We are still advised to use vue’s proxy object.defineProperty (), but the library has not been updated for four years and is still running stably and is well accepted by koA developers.

other

Request. js and Response. js files are nothing to talk about, but specific tool method implementation, convenient for developers to call, interested in reading the source code.

application

The whole Node service of Zhaopin front-end architecture is based on KOA implementation, including our VUE server rendering and Node restful API, etc.

We chose KOA because it is lightweight, scalable, supports async, await async, and gets rid of callback hell.

There are also mature koA2-based enterprise-level solutions, such as EggJS and ThinkJS.

conclusion

Removing the mystery of KOA allows developers to focus on business logic as well as the framework itself, which is conducive to troubleshooting and writing extensions. At the same time, you can learn the ideas of express, HAPI and other types of frameworks, combine existing enterprise-level solutions, and choose a framework that suits you. In short, whether the framework is good or bad, it only depends on the scenario.