1 Environment setup, creation, and operation

1.1 introduction

Egg.js is a Node enterprise application development framework based on Node. js and KOA, which can help development teams and developers reduce costs. Based on KOA2, ES6, and ES7, Node has a more standardized development model, lower learning costs, more elegant code, and less maintenance costs.






1.2 Environment Construction

NPM I egg-init -g/CNPM I egg-init -g/NPM I egg-init -g/NPM I egg-init -g No Spaces)

1.3 create

$NPM I egg-init -g $egg-init egg-example --type=simple // example :egg-init project name --type=simple $cd egg-example
$ npm i
Copy the code

1.4 Running the Project

NPM run dev open localhost:7001 // Generally, the default port is 7001Copy the code

2 Directory structure

2.1 Directory Structure

An egg - project ├ ─ ─ package. Json ├ ─ ─ app. Js (optional) ├ ─ ─ agent. The js (optional) ├ ─ ─ app (project directory) | ├ ─ ─ the router, js (used to configure the URL routing rules) │ ├ ─ ─ Controller (used to parse user input, Return the corresponding results after processing) │ | └ ─ ─ home. Js │ ├ ─ ─ service (for writing business logic layer) │ | └ ─ ─ the user. The js │ ├ ─ ─ middleware (for writing middleware) │ | └ ─ ─ Response_time. Js │ ├ ─ ─ the schedule (optional) │ | └ ─ ─ my_task. Js │ ├ ─ ─ public (for static resources) │ | └ ─ ─ reset. CSS │ ├ ─ ─ the view (optional) │ | └ ─ ─ home. TPL │ └ ─ ─ the extend (for the expansion of the framework) │ ├ ─ ─ helper. Js (optional) │ ├ ─ ─ request. Js (optional) │ ├ ─ ─ the response. The js (optional) │ ├ ─ ─ the context, js (optional) │ ├ ─ ─ application. Js (optional) │ └ ─ ─ agent. The js (optional) ├ ─ ─ the config (used to write configuration files) | ├ ─ ─ the plugin, js (used in configuration needs to be loaded plug-ins) | ├ ─ ─ Config. Default. Js │ ├ ─ ─ config. Prod. Js | ├ ─ ─ config. The test. The js (optional) | ├ ─ ─ config. Local, js (optional) | └ ─ ─ config. The unittest. Js (Optional) ├ ─test(for a unit test) ├ ─ ─ middleware | └ ─ ─ response_time. Test. The js └ ─ ─ controller └ ─ ─ home. Test. JsCopy the code

3 Access Route

Egg’s design fully conforms to the better MVC design pattern.

3.1 So what is MVC?

The full name is Model View Controller, which is an abbreviation of Model – View – Controller, a Model of software design.

View, Controller, and data models Model (Service) and configuration file (config) in egg

3.2 Controller (Controller)

  • app/controllerThe Controller is implemented below the directory
// app/controller/home.js

const Controller = require('egg').Controller;

class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = 'hi, world'; }}module.exports = HomeController;

Copy the code

Enter NPM run dev to view http://127.0.0.1:7001 and output hi, world

I think of a controller as an interface that manages inputs and outputs

* You can also write many of these js files in the app/ Controller directory to represent the interface

3.3 Router

The app/router.js file is used to unify all routing rules.

Now a lot of single pages, there are relative to the route, you write a JS, also have to write a route

// app/controller/user.js
class UserController extends Controller {
  async info() {
    const { ctx } = this;
    ctx.body = {
      name: `hello ${ctx.params.id}`}; }}Copy the code
// app/router.js
module.exports = app= > {
  const { router, controller } = app;
  router.get('/user/:id', controller.user.info);
};
Copy the code

3.4 Data Model Model (Service)

Simply put, a Service is an abstraction layer used to encapsulate business logic in complex business scenarios. Providing this abstraction has the following benefits:

  • Keep the logic in the Controller cleaner.
  • To keep the business logic independent, the abstract Service can be repeatedly called by multiple controllers.
  • Separating logic from presentation makes it easier to write test cases.
// app/service/user.js
const Service = require('egg').Service;

class UserService extends Service {
  async addName(name) {
    const user = Hi, `${name}`;
    returnuser; }}module.exports = UserService;
Copy the code
// app/controller/user.js
class UserController extends Controller {
  async info() {
    const { ctx } = this;
    const userInfo = await ctx.service.user.addName('wjw'); ctx.body = userInfo; }}Copy the code

3.5 View in egg

Template rendering in egg, but I think the separation of front-end and back-end is more conducive to design as a service architecture, so I don’t describe the view construction here

4 Get and POST requests

4.1 get request

4.1.1 query

In the URL? The latter part is a Query String, which is often used to pass parameters in GET requests. For example, GET/search? Name =egg&age=26 Name =egg&age=26 is the parameter passed by the user. We can retrieve the parsed body using context.query(for an object)

module.exports = app= > {

class HomeController extends Controller {
  async getQuery() {
      const queryObj = this.ctx.query;
      console.log(queryObj.age);
      console.log(queryObj);
      {name: 'egg', age: '26'}}}return SearchController;
};
Copy the code

When a key in a Query String is repeated, context. Query takes only the value of the key when it first occurs, and subsequent occurrences are ignored. GET /posts? Category =egg&category=koa Context. query gets {category: ‘egg’}.

4.1.2 the queries

Sometimes our system is designed to have users pass the same key, like GET /posts? Category = egg&id = 1 & id & id = 3 = 2. This object also parses the Query String, but it does not discard any duplicate data. Instead, it puts them all in an array:

// GET /posts? category=egg&id=1&id=2&id=3
const Controller = require('egg').Controller;

class HomeController extends Controller {
  async getQueries() {
    console.log(this.ctx.queries);
    //result:
    / / {
    // category: [ 'egg' ],
    // id: [ '1', '2', '3' ],
    // }}};Copy the code

Context. Queries all keys must be array types if they have values.

4.2 a post request

// Get parameter method post request


module.exports = app= > {
class HomeController extends Controller {
  async postObj() {
      constqueryObj = ctx.request.body; ctx.body = queryObj; }}return SearchController;
};
Copy the code

But we request sometimes get, sometimes POST, sometimes should have been POST request, but for the convenience of testing, or make get and POST request support request, so a middleware can get and POST request parameters at the same time is very necessary.

4.3 Write an intermediate layer to solve GET and POST requests

4.3.1 Create a new Middleware folder in the app directory

4.3.2 Create params.js in middleware as follows

Middleware * can use ctx.params to get or post request parameters */
module.exports = options= > {
  return async function params(ctx, next) { ctx.params = { ... ctx.query, ... ctx.request.body }await next();
  };
};
Copy the code

In essence, we put both the PARAMETERS of the GET request and the parameters of the POST request into params, so that both get and POST can get the request parameters

4.3.3 at/config/config. Default. Injection of middleware in js

'use strict';
module.exports = appInfo= > {
  const config = exports = {};
// Inject middleware
  config.middleware = [
    'params',];return config;
};
Copy the code

4.3.4 Obtaining using articles

/** * Add article interface */
'use strict';
const Service = require('egg').Service;
class ArticleService extends Service {
  async add() {
    const { ctx } = this;
    // Get the request parameters
    const {
      userId,
      title,
      content,
    } = ctx.params;
    const result = await ctx.model.Article.create({
      userId,
      title,
      content,
    });
    returnresult; }}module.exports = ArticleService;
Copy the code

4.3.5 Allowing POST Requests across domains

// config/plugin.js
exports.cors = {
  enable: true.package: 'egg-cors'};Copy the code
 // config/config.default.js
config.security = {
  csrf: {
    enable: false.ignoreJSON: true,},domainWhiteList: [ 'http://www.baidu.com'].// Configure the whitelist
};

config.cors = {
  // origin: '*',// allows all cross-domain access, comment out to allow above whitelist access
  allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'};Copy the code

* It is best to use white list in general, do not use all allow cross domain, unsafe

5 mysql Database

The framework provides the egg-mysql plug-in to access the mysql database. This plug-in can access both a normal MySQL database and an online database service based on the MySQL protocol.

5.1 Installation and Configuration

Install the following plugin:

npm i --save egg-mysql
Copy the code

Enable plug-in:

// config/plugin.js
exports.mysql = {
  enable: true.package: 'egg-mysql'};Copy the code

Configure database connection information for each environment in config/config.${env}.js.

5.1.1 Single data source

If our application needs to access only one instance of MySQL database, it can be configured as follows:

// config/config.${env}.js
exports.mysql = {
  // Configure single database information
  client: {
    // host
    host: 'mysql.com'./ / the port number
    port: '3306'./ / user name
    user: 'test_user'./ / password
    password: 'test_password'.// Database name
    database: 'test',},// Whether to load to app, enabled by default
  app: true.// Whether to load it to the agent
  agent: false};Copy the code
await app.mysql.query(sql, values); // Single instances can be accessed directly through app.mysql
Copy the code

5.1.2 Multiple data sources

If our application needs to access multiple MySQL data sources, the following configuration can be used:

exports.mysql = {
  clients: {
    Get ('clientId') to obtain the client instance
    db1: {
      // host
      host: 'mysql.com'./ / the port number
      port: '3306'./ / user name
      user: 'test_user'./ / password
      password: 'test_password'.// Database name
      database: 'test',},db2: {
      // host
      host: 'mysql2.com'./ / the port number
      port: '3307'./ / user name
      user: 'test_user'./ / password
      password: 'test_password'.// Database name
      database: 'test',},// ...
  },
  // Default values for all database configurations
  default: {},// Whether to load to app, enabled by default
  app: true.// Whether to load it to the agent
  agent: false};Copy the code

5.2 Encapsulation add, delete, change and check

5.2.1 Insert, insert a data into the Users table

const result = await this.app.mysql.insert('users', {
    name: 'wjw'.age: 18
  })
// Judge: result.affectedRows === 1
Copy the code

Select * from users where name=Jack

const result = await this.app.mysql.select('users', {
    columns: ['id'.'name'].// select * from *
    where: {
        name: 'wjw'
    }, // Query conditions
    orders: [
        ['id'.'desc'] // descending desc, ascending ASC].limit: 10.// Query the number of entries
    offset: 0 // Data offset (paged query)
  })
// judge: result.length > 0
Copy the code

Alter table users where id=1 and age = 20

const result = await this.app.mysql.update('users', {
      age: 20 // Data to be modified
  }, {
      where: {
        id: 1
      } // Modify query conditions
  });
// Judge: result.affectedRows === 1
Copy the code

Select * from users where name= WJW

const result = await this.app.mysql.delete('users', {
    name: 'wjw'
})
Copy the code

6 Use of cookies

6.1 introduction of cookies

  • Cookies are variables stored on the visitor’s computer. It allows us to share data when accessing the same domain using the same browser.
  • HTTP is a stateless protocol. Simply put, when you visit a page and then go to another page on the same site, the server cannot recognize that it is the same browser visiting the same site. Every visit, there is no relationship.

6.2 Setting and obtaining cookies

6.2.1 Syntax for setting cookies

ctx.cookies.set(key, value, options)

this.ctx.cookies.set('name'.'zhangsan');
Copy the code

6.2.2 Cookie Acquisition Syntax

ctx.cookies.get(key, options)

this.ctx.cookies.get('name')
Copy the code

6.2.3 clear cookies

this.ctx.cookies.set('name'.null);
Copy the code

Or set the maxAge expiration time to 0

6.3 Cookie Parameter Options

Eggjs.org/en/core/coo…

ctx.cookies.set(key, value, {
  maxAge:24 * 3600 * 1000.httpOnly: true.// This is correct by default
  encrypt: true.// Cookies are encrypted during network transmission
  ctx.cookies.get('frontend-cookie', {
  encrypt: true
});
Copy the code

6.4 Setting Chinese Cookies

6.4.1 Solution 1

console.log(new Buffer('hello, world! ').toString('base64'));
// Convert to base64 string: aGVsbG8sIHdvcmxkIQ==
console.log(new Buffer('aGVsbG8sIHdvcmxkIQ=='.'base64').toString()); // Restore base64 string: hello, world!
Copy the code

6.4.2 Second solution

ctx.cookies.set(key, value, {
	maxAge:24 * 3600 * 1000.httpOnly: true.// This is correct by default
	encrypt: true.// Cookies are encrypted during network transmission
});
Copy the code

7 Use of Session

7.1 Session Introduction

Session is another mechanism for recording the client’s state, except that cookies are stored in the client browser, while sessions are stored on the server.

7.2 Session Workflow

When the browser accesses the server and sends the first request, the server creates a session object, generates a key-value pair similar to key and value, and returns the key(cookie) to the browser (client). The browser carries the key(cookie) when it accesses the server the next time. Find the corresponding session(value).

7.3 Use of session in egg.js

Session operations are built into egg-session in egg.js

7.3.1 set

this.ctx.session.userinfo={
	name:'Joe'.age:'20'
}
Copy the code

7.3.2 for

var userinfo=this.ctx.session
Copy the code

7.3.3 Default Session Settings

exports.session = {
  key: 'EGG_SESS'.maxAge: 24 * 3600 * 1000.// 1 day httpOnly: true,
  encrypt: true
};
Copy the code

7.4 Configuring Session in config.default.js

config.session={
  key:'SESSION_ID'.maxAge:864000.renew: true // Extend the validity of the session
}
Copy the code

7.5 Differences between Cookies and Sessions

  • Cookie data is stored on the client’s browser and session data is stored on the server.
  • Cookies are less secure than sessions. Other people can analyze cookies stored locally and cheat cookies.
  • Sessions are stored on the server for a certain amount of time. Cookies should be used to reduce server performance when the number of accesses increases.
  • A single cookie can hold no more than 4K of data, and many browsers limit the number of cookies a site can hold to 20.

8 Scheduled tasks & fixed tasks

Egg provides a powerful timed task system. Scheduled tasks enable the system to modify the cache data of a service to process the data that needs to be periodically updated.

Create a new JS file in the app/schedule directory. Each JS file is a scheduled task



// app/schedule
module.exports = {
  schedule: {
    interval: '1m'.// 1 minute interval
    type: 'all'.// specify that all workers need to be executed
  },
  async task(ctx) {
    i++
    console.log(i)
  },
};

/* Comments: 1ms -> 1ms 1s -> 1sec 1m -> 1 minute */
Copy the code

8.2 Fixed Tasks

Fixed-point missions (take the leaderboard update at 5:30am on Monday as an example)

1. Use the CRon parameter to set the time. The CRON parameter is divided into 6 parts

* * * * * * ┬ ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ | │ │ │ │ │ └ week (0 to 7) on Sunday (0 or 7 is │ │ │ │ └ ─ ─ ─ ─ ─ a month (1-12) │ │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ date (1 - 31) │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ hours (0-23) │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ minutes (0-59) └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ seconds (0 to 59, optional)Copy the code
// app/schedule
module.exports = {
  schedule: {
    cron: '0 30 5 * * 1'.// Update every Monday at 5:30am
    type: 'all'.// specify that all workers need to be executed
  },
  async task(ctx) {
    i++
    console.log(i)
  },
};
Copy the code

8.3 Perform a scheduled task only once

If the immediate parameter is set to true, the scheduled task is executed immediately after the project starts

module.exports = {
  schedule: {
    interval: '1m'.// 1 minute interval
    type: 'all'.// specify that all workers need to be executed
    immediate: true.// Execute a scheduled task upon project startup
  },
  async task(ctx) {
    i++
    console.log(i)
  },
};
Copy the code

8.4 Closing a Task

If disable is set to true, the scheduled task is disabled

8.5 Specifying the Scheduled Task Execution Environment env

env: ["dev"."debug"] // This scheduled task is executed only in the development environment and debug mode
Copy the code

9 the deployment

9.1 Deploying a Server

The first step, of course, is to deploy the Node service on your server and then install it.

Node.js must be installed on the server. The framework supports Node version >= 8.0.0. Egg-cluster is built into the framework to start the Master process, which is stable enough to eliminate the need for pM2 daemon modules. The framework also provides egg-scripts for running and stopping online environments.

egg-scripts start --port=7001 --daemon --title=egg-server-showcase
Copy the code
  • --port=7001Port number, which reads environment variables by defaultprocess.env.PORTIf not passed, frame built-in port will be used7001.
  • --daemonWhether to allow background mode? Nonohup. If using Docker, it is recommended to run directly in the foreground.
  • --env=prodThe framework runs the environment, which reads environment variables by defaultprocess.env.EGG_SERVER_ENVIf not passed, the frame built-in environment will be usedprod.
  • --workers=2Frame number of worker threads. By default, the number of app workers equal to the number of CPU cores will be created to make full use of CPU resources.
  • --title=egg-server-showcaseGrep is used to facilitate ps process. The default value is grepegg-server-${appname}.
  • --framework=yadanIt can be configured if the application uses itpackage.json 的 egg.frameworkOr specify this parameter.
  • --ignore-stderrIgnore errors reported during startup.

9.1.1 Starting configuration Items

You can also specify startup configuration in config.{env}.js.

// config/config.default.js

exports.cluster = {
  listen: {
    port: 7001.hostname: '127.0.0.1'.// path: '/var/run/egg.sock',}}Copy the code

Path, port, and hostname are parameters of server.listen. The port passed by the egg-scripts and egg.startCluster methods has a higher priority than this configuration. s

9.1.2 Stop Commands

This command kills the master process and tells the worker and agent to exit gracefully. The following parameters are supported:

  • --title=egg-serverKills the specified egg application, or terminates all egg applications if it is not delivered.
"start": "egg-scripts start --daemon --title=${process name}"."stop": "egg-scripts stop --title=${process name}"
Copy the code
  • Or you can just go through
ps -eo "pid,command" | grep -- "--title=egg-server"
Copy the code

Find the master process and kill it without killing -9.

Because egg knowledge is too much, it is divided into two chapters

takeaway

Egg – From Entry to Entry (ii)

An egg – mongoose project