egg js build project, tutorial

Egg.js

construction project

Egg.js is born for enterprise-level frameworks and applications. We hope that Egg.js will breed more upper-level frameworks to help development teams and developers reduce development and maintenance costs.

official website

  • Use Scaffolding to build the application to quickly initialize the project

npm init egg --type=simple
npm i
  • At this point the directory structure is as follows

Write the control layer in app>controller>??.js
Write the routing matching rules in app>router.js
egg-example
├── app
│   ├── controller
│   │   └── home.js
│   └── router.js
├── config
│   └── config.default.js
└── package.json
  • The home.js code is as follows

// app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
  async index() {
    this.ctx.body = 'Hello world';
  }
}
module.exports = HomeController;
  • The router.js code is as follows

// app/router.js
module.exports = (app) => {
  const { router, controller } = app;
  router.get('/', controller.home.index);
};

Routing and Controllers

Router

Router is mainly used to describe the corresponding relationship between the request URL and the Controller responsible for executing the action. The framework stipulates that the app/router.js file is used to unify all routing rules.

internal redirect

// app/router.js
module.exports = (app) => {
  app.router.get('index', '/home/index', app.controller.home.index);
  app.router.redirect('/', '/home/index', 302);
};

too many route maps

As mentioned above, we do not recommend that the routing rule logic be scattered in multiple places, which will cause trouble for troubleshooting.
'use strict';
const routers = {
  home(router, controller) {
    return router.get('/home', controller.home.index);
  },
}
/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app;
  // 路由配置
  Object.values(routers).forEach((item) => {
    item(router, controller)
  })
};

RESTful style configuration

RESTful

If you want to define routing in a RESTful way, we provide app.router.resources('routerName', 'pathMatch', controller) to quickly generate a CRUD routing structure on a path.
// app/router.js
module.exports = (app) => {
  const { router, controller } = app;
  router.resources('posts', '/api/posts', controller.posts);
  router.resources('users', '/api/v1/users', controller.v1.users); // app/controller/v1/users.js
};
The above code deploys a set of CRUD path structures on the /posts path, and the corresponding Controller is app/controller/posts.js Next, you only need to implement the corresponding functions in posts.js.
// app/controller/posts.js
const { Controller } = require('egg');
class Posts extends Controller {
    index() {
        this.ctx.body = '获取列表';
    };
    new() {
        this.ctx.body = '新增表单';
    };
    show() {
        this.ctx.body = '博客详情';
    };
    edit() {
        this.ctx.body = '编辑页面';
    };
    create() {
        this.ctx.body = '新增博客';
    };
    update() {
        this.ctx.body = '修改博客';
    };
    destroy() {
        this.ctx.body = '删除博客';
    };
}
module.exports = Posts;

static resources

The egg-static plug-in is used internally to complete
all files in the app > public directory.
Visit http://localhost:7002/public/index.html
to obtain app/public/index.html file information

plug-in

plug-in

The egg plug-in naming convention is egg-*
For example, the static plug-in name is egg-static

Activation of the plug-in

After the installation is complete, the plug-in is not enabled, and the plug-in needs to be enabled in config/plugin.js.
Built-in plugins are automatically started.
/** @type Egg 的插件 */
module.exports = {
  // 插件名称
  static: {
    enable: true,//是否启用
    package: "egg-static",//插件包名
    // path:"",//自定义插件 跟package只能出现一个
  },
};

plugin configuration

Plug-ins generally contain their own default configuration, and application developers can override the corresponding configuration in config.default.js:
// config/config.default.js
module.exports = appInfo => {
  const config = exports = {};
  // cookie签名
  config.keys = appInfo.name + '_1678169356863_9169';
  // 添加用户配置
  const userConfig = {
    // myAppName: 'egg',
  };
    // 配置static插件
  exports.static = {
    prefix: '/',
  };
  return {
    ...config,
    ...userConfig,
  };
};

egg-view-ejs template engine

// {app_root}/config/plugin.js
exports.ejs = {
  enable: true,
  package: 'egg-view-ejs',
};

// {app_root}/config/config.default.js
exports.view = {
  mapping: {
    '.ejs': 'ejs',
  },
};

middleware

The middleware form of Egg is the same as that of Koa, both of which are based on the onion ring model. Every time we write a middleware, it is equivalent to wrapping a layer outside the onion.
middleware

koa middleware

// app/middleware/bodyparser.js
// koa-compress 暴露的接口(`(options) => middleware`)和框架对中间件要求一致
module.exports = require('koa-bodyparser');

//app/config/config.default.js
// 配置需要的中间件,数组顺序即为中间件的加载顺序
config.middleware = ['bodyparser'];     

global middleware

// app/middleware/myMiddleware.js
//一个中间件
module.exports = (options) => {
  return async function myMiddleware(ctx, next) {
    await next();
  };
};   
//配置config.default.js
module.exports = {
  // 配置需要的中间件,数组顺序即为中间件的加载顺序
  middleware: ['myMiddleware'],
  // 配置 myMiddleware中间件的配置
  myMiddleware: {
      enable:boolean,//是否启用中间件
      match:"/login",//匹配为true才运行中间件
      ignore:"/api",//忽略那些路径
  }
};

routing middleware

routing middleware

Using middleware for a route controller
app/router.js
resources(router, controller, app) {
    const myMiddleware = app.middleware.myMiddleware({ a: 1024 });
    router.resources('blogs', '/api/blogs', myMiddleware, controller.blogs);
}

Service

Simply put, Service is an abstraction layer for business logic encapsulation in complex business scenarios. Providing this abstraction has the following advantages:
Keep the logic in the Controller more concise.
To maintain the independence of business logic, the abstracted Service can be called repeatedly by multiple Controllers.
Serve

Define Service

// app/service/user.js
const Service = require('egg').Service;
class UserService extends Service {
  async find(uid) {
    const user = await this.ctx.db.query(
      'select * from user where uid = ?',
      uid,
    );
    return user;
  }
}
module.exports = UserService;

access service

Service files must be placed in the app/service directory, which can support multi-level directories, and can be cascaded through directory names when accessing.
ctx.service.syncUser.func(params)
app/service/biz/user.js => ctx.service.biz.user
app/service/sync_user.js => ctx.service.syncUser
// app/controller/user.js 控制层访问
const Controller = require('egg').Controller;
class UserController extends Controller {
  async info() {
    const { ctx } = this;
    const userId = ctx.params.id;
    const userInfo = await ctx.service.syncUser.find(userId);
    ctx.body = userInfo;
  }
}
module.exports = UserController;

database

MySql database

egg-sequelize

In some more complex applications, we may need an ORM framework to help us manage the code of the data layer. In the Node.js community, sequelize is a widely used ORM framework that supports multiple data sources such as MySQL, PostgreSQL, SQLite, and MSSQL.
Sequelize framework
  • Install

npm install --save egg-sequelize mysql2

  • Introduce the egg-sequelize plugin in config/plugin.js

exports.sequelize = {
  enable: true,
  package: 'egg-sequelize',
};
  • Write sequelize configuration in config/config.default.js

  exports.sequelize = {
    logging: false,
    dialect: 'mysql',
    host: '127.0.0.1',
    port: 3306,
    database: 'myegg',
    username: "root",
    password: "5201314025ma",
    define: {
      timestamps: false, // 关键配置,默认为 true, 修改为 false 即可
      freezeTableName: false,
    }
  };

Model Definition and Simulation Data

Model definition, model synchronization, simulate data, establish table relationship.

data simulation

// app/model/user 模型

// const Mock = require("mockjs")
// const resultStu = Mock.mock({
//     "datas|200-300": [
//         {
//             "id|+1": 1,
//             name: "@cname",
//             loginId: "@id",
//             loginPwd: /\w{10}/,
//             created_at: "@date",
//             updated_at: "@date",
//             "auth|1": ['user', 'admin'],

//         }
//     ]
// }).datas;

module.exports = (app) => {
    const { STRING, INTEGER, DATE } = app.Sequelize;
    const User = app.model.define('user', {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true },
        name: STRING(20),
        loginId: { type: STRING(20), allowNull: false },
        loginPwd: { type: STRING, allowNull: false },
        created_at: DATE,
        updated_at: DATE,
        auth: STRING(20),
    });

    User.associate = function () {
        app.model.sync({ alter: true }).then(() => {
            console.log(19, '所有同步完成');
        })
        app.model.Class.hasMany(app.model.Student);
        app.model.Student.belongsTo(app.model.Class);
        console.log(22, '关联表');
        // app.model.Student.bulkCreate(resultStu);
    };
    return User;
};

controller class

app/controller/class.js
//查询
const { Controller } = require('egg');
class Class extends Controller {
    async index() {
        const ctx = this.ctx;
        const query = ctx.query
        //调用service
        ctx.body = await ctx.service.class.find(query);
    }
}
module.exports = Class;

service class

app/service/class
const Service = require('egg').Service;
class UserService extends Service {
    async find(query) {
        const { page, limit } = query;
        const result = await this.ctx.model.Class.findAndCountAll({
            offset: (+page - 1) * +limit,
            limit: +limit,
            include: [this.ctx.model.Student],
        })
        return (result);
    }
}
module.exports = UserService;

egg-redis

redis

  • Install

npm i egg-redis --save

//config/plugin.js
exports.redis = {
    enable: true,
    package: 'egg-redis',
}

//config.default.js
config.redis = {
    client: {
      port: 6379,          // Redis port
      host: '127.0.0.1',   // Redis host
      password: 'auth',    //必填
      db: 0,
    },
}
app/controller/user.js
const { Controller } = require('egg');
class Posts extends Controller {
  async index() {
    await this.app.redis.set('foo', 'bar11111111111');
    // get
    this.ctx.body = await this.app.redis.get('foo');
  }
}

Guess you like

Origin blog.csdn.net/weixin_55508765/article/details/129413344