This article has participated in the activity of “New person creation Ceremony”, and started the road of digging gold creation together.

background

Before based on an Egg. Js developed several projects, found that every project has A configuration file, database connection, the data model definition, operation WeChat processing functions such as login authorization, and make A new project always before copying program to delete bowdlerize change, sometimes in A project to add A practical function, B project add A cool tool function, But later forgotten, there is no unified precipitation place, so made a scaffold, one new project development can be out of the box, and two is also convenient for technology precipitation.

positioning

Back-end scaffolding based on egg.js.

Egg.js encapsulates a layer that aggregates common functionality closer to the business, and if egg.js is a noodle, the back-end scaffolding is a noodle.

Function is introduced

The module Function is introduced The progress of
Database operations Built-in ORM Egg-Sequelize plug-in as a database operation library, can be adapted to Postgres, MySQL, MariaDB, SQLite database Square root
Interface Route Configuration The built-in egg-router-plus plug-in solves the routing namespace problem Square root
Automatically generate interface documents The built-in egg-Swagger-doc plug-in can automatically generate interface usage documents by writing interface annotations according to the convention Square root
Field calibration The built-in egg-validate-Plus plug-in can be used alone or in conjunction with egg-Swagger-doc plug-in as field verification, which can automatically generate interface documents and realize field verification Square root
Multi-environment Configuration Built-in local development environment, test environment and production environment configuration, switching and extension is very easy Square root
Cross-domain configuration Different cross-domain configurations are configured in multiple environments to meet different requirements for cross-domain policies in different environments Square root
Exception handling Unified encapsulation processes thrown errors and does not directly throw errors to the front-end, improving security and better front-end experience Square root
Tool library Encapsulate menu tree processing, version number comparison, UID generation and other common tool functions, more convenient development Square root
Unit testing Complete unit testing, more robust code Square root
Wechat mini program login The whole process of authorized login and obtaining mobile phone number of wechat mini program is built in, which can be seamlessly connected with wechat mini program Square root
eslint Strict and complete ESLint rules are built in to ensure code specification and more efficient co-development Square root

The project structure

.├ ── LICENSE ├─ readme.mdPlease read me before you mess up├ ─ ─ the app# main program code directory│ ├ ─ ─ contractGenerate data structures for interface documentation automatically│ ├ ─ ─ the controller# controller│ ├ ─ ─ the extend# Framework extension│ ├ ─ ─ middleware# middleware│ ├ ─ ─ model# Data model│ ├ ─ ─ the publicPublic static resources│ ├ ─ ─ the router. Js# Route configuration│ └ ─ ─ the service# service├ ─ ─ app. Js# entry├─ Appveyor.yML ├─ config │ ├─ config.default.jsDefault configuration, including custom application configuration, security policy, cookie, cross-domain, permission, etc│ ├ ─ ─ config. Local. JsLocale-specific configuration items│ ├ ─ ─ config. Prod. JsProduction environment specific configuration items│ ├ ─ ─ config. Test. JsTest environment-specific configuration items│ ├ ─ ─ config. Unittest. JsUnit test environment-specific configuration items│ └ ─ ─ plugin. Js# plugins, which can be custom enabled to disable certain plugins├─ JsConfig. json ├─ Note │ ├─ database.sqlCreate database script│ ├ ─ ─ note. The md# Project Development Notes│ └ ─ ─ tables. SQLCreate table user script├ ─ ─ package. Json ├ ─ ─test                   # Unit tests│ ├ ─ garbage ─ impCopy the code

Project configuration

If there is no database, run the following SQL to create a new database:

CREATE DATABASE IF NOT EXISTS template_node_egg DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;
Copy the code

Then import the user table:

/* Navicat Premium Data Transfer Source Server: 50722 Source Host : localhost:3306 Source Schema : template_node_egg Target Server Type : MySQL Target Server Version : 50722 File Encoding : 65001 Date: 02/01/2022 23:22:25 */

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `open_id` varchar(255) NOT NULL COMMENT 'Same as wechat openID',
  `union_id` varchar(255) DEFAULT NULL COMMENT 'Same as wechat's unionID, as a reserved field, may not have a value',
  `nick_name` varchar(255) NOT NULL COMMENT 'nickName',' nickName',
  `password` varchar(255) DEFAULT NULL COMMENT 'Login password, as a reserved field, may not have a value',
  `avatar_url` text NOT NULL COMMENT 'Avatar, same as wechat avatarUrl',
  `phone` varchar(255) DEFAULT NULL COMMENT 'Mobile number, may be empty',
  `gender` int(11) DEFAULT NULL COMMENT 'Gender, may be empty',
  `country` varchar(255) DEFAULT NULL COMMENT 'The country may be empty',
  `province` varchar(255) DEFAULT NULL COMMENT 'Province, possibly empty',
  `city` varchar(255) DEFAULT NULL COMMENT 'The city may be empty',
  `language` varchar(255) DEFAULT NULL COMMENT 'Language, may be empty',
  `logged_at` datetime DEFAULT NULL COMMENT 'Last Login Time',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL.PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of user
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES (1.'o8FXk5E4u7hwaguN6kSq-KPXApJ1'.NULL.'Test account'.NULL.'https://gimg2.baidu.com/image_search/src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180520%2F0473e00bdfd247 6 fbe0c228a45a1652c.jpeg&refer=http%3a%2f%2f5b0988e595225.cdn.sohucs.com & app = 2002 & size = f9999, 10000 & q = a80 & n = 0 & g = 0 n & FMT =, jpe. g?sec=1628131130&t=05ee794a54bad8edd2fd8bb2536db5b9'.NULL.NULL.NULL.NULL.NULL.NULL.'the 2022-01-01 23:59:59'.'the 2022-01-01 23:59:59'.'the 2022-01-01 23:59:59');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
Copy the code

If yarn dev is started for the first time, you may need to change the password in config/config.local.js:

config.sequelize = {
  // Connect to the user
  username: 'root'.// Connect password
  password: ' '.// The connected database can be changed to an existing database as required
  database: 'template_node_egg'.// Connection address
  host: '127.0.0.1'.// Database type
  dialect: 'mysql'
}
Copy the code

If the user field in the existing database does not match the field defined in model/user.js, you need to modify it by yourself. Otherwise, an error will be reported

Application configuration

User-defined application configurations take effect globally after modification.

// The prefix of the interface, which varies with the service system
const apiPrefixName = 'api'
// Complete prefix of the interface
const apiPrefix = ` /${apiPrefixName}`
// Background interface prefix, which is modified with the service system
const manageApiPrefixName = 'manage'
// Background interface prefix
const manageApiPrefix = ` /${manageApiPrefixName}`
const userConfig = {
  // The application name is used to specify the directory of the log file and the key of the cookie. It is unique. The default is app.name and can also be changed to other strings
  appName: app.name,
  apiPrefixName,
  apiPrefix,
  manageApiPrefixName,
  manageApiPrefix,
  // The default code and error message configuration, just need to change this one place
  resCode: {
    // Successful code identifier
    success: {
      code: 0
    },
    // Error code flag and prompt
    error: {
      code: 602.message: 'Parameter exception'
    },
    // Server exception code identifier and prompt
    serverError: {
      code: 500.message: 'Server exception'
    },
    // Code identifier and prompt for not logged in
    notLogged: {
      code: 601.message: 'Please log in before you operate'}}}Copy the code

Cookie configuration

Scaffolding has built-in application (such as applets) interface services and background interface services, where the field configuration is basically unchanged. The background interface service is optional and can be ignored if you do not want to put it together.

The application interface service uses ctx.session.[keyName] to set and retrieve values. For example, to set the ID field to cookie, set the cookie as follows:

ctx.session.id = 1
Copy the code

Getting a cookie is:

ctx.service.user.info(ctx.session.id)
Copy the code

Ctx. cookies. Get (key, cookie) method is required for background interface service acquisition. For specific usage, see ctx.cookies usage document here.

Security Policy Configuration

  • Scaffolding enables security policies provided by egg.js by default.

  • Scaffolding is cross-domain by default, but this setting is turned off in production and whitelisted automatically, making it easier to start development:

// Front-end port. Change the value as required
const port = 9001
const domainWhiteList = [
  ...new Set([
    ` http://127.0.0.1:${port}`.`http://localhost:${port}`.// When the service starts, it tries to automatically obtain the whitelist of local IP Settings
    `http://${getLocalhost()}:${port}`
  ])
]
config.security = {
  domainWhiteList
}
// Cross-domain is allowed by default. This is disabled in production environments
config.cors = {
  origin: The '*'.allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
}
Copy the code

Access configuration

The interface service with login system basically needs to specify a part of the interface that can be accessed without login. Scaffolding has built-in whitelist interface related to login:

[
  `${apiPrefix}/user/mock`.`${apiPrefix}/user/login`.`${apiPrefix}/user/logout`.`${apiPrefix}/user/phone`
]
Copy the code

Automatically generate document configuration

The built-in egg-Swagger-doc plug-in can automatically generate interface usage documents by writing interface annotations according to the convention. All data model structures are defined in APP/Contract.

See egg-swagger-doc here for details.

If this function is not required, you can also disable automatic document generation in config/plugin.js:

{
  swaggerdoc: {
    enable: false.package: 'egg-swagger-doc'}}Copy the code

The development of

Generally, the following four steps are required to develop a new interface:

The new model

Add a new log.js file to app/model and add the data model:

'use strict'

/** ** log table */

module.exports = app= > {
  // The data type provided by sequelize.js
  const { STRING } = app.Sequelize

  const Log = app.model.define(/* Table name */ 'log', {
    // Table fields
    content: {
      // Field type
      type: STRING(255),
      // Field comments
      comment: 'Operation content'
    },
    remarks: {
      type: STRING(255),
      allowNull: false.comment: 'note'
    },
    actionType: {
      type: STRING(255),
      comment: 'Operation type'}})return Log
}

Copy the code

The new service

Add a log.js file to app/service and add a database operation to get the list:

'use strict'

const Service = require('egg').Service

class LogService extends Service {
  // Get the log list
  async logs(actionType) {
    const { ctx } = this
    try {
      const data = await ctx.model.Log.findAll({
        where: {
          actionType
        }
      })
      return ctx.helper.clone(data)
    } catch (error) {
      ctx.logger.error(error)
    }
    return false}}module.exports = LogService

Copy the code

Adding a Controller

Add a new logInfo model to app/contract/ to.js:

{
  // ...

  logInfo: {
    content: { type: 'string'.description: 'Operation content' },
    remarks: { type: 'string'.description: 'note' },
    actionType: { type: 'string'.description: 'Operation type'}}}Copy the code

Then add a new log.js file to app/ Controller and add a method to get the list:

'use strict'

const Controller = require('egg').Controller

/ * * *@controller Log Log module */
class LogController extends Controller {
  / * * *@summary Gets a list of action records *@description Queries the list of user actions * based on the specified filter criteria@router get /log/logs
   * @response 0 logInfo Log list */
  async logs() {
    const { ctx } = this
    const { actionType } = ctx.request.query

    // Check parameters
    const rules = {
      actionType: { required: true.message: 'Operation type cannot be null'}}const passed = await ctx.validate(rules, ctx.request.query)
    if(! passed)return

    const data = await ctx.service.log.logs(actionType)
    if (data) {
      this.ctx.helper.success(data)
    } else {
      this.ctx.helper.error(null.'Log list failed')}}}module.exports = LogController

Copy the code

The new interface

Add a routing interface to app/router.js:

// Get the log list
subRouter.get('/log/logs', controller.log.logs)
Copy the code

The above example is certainly simple, but that’s the general procedure.

Of course, when adding an interface, it is not necessary to add a new controller file, basically is to add a method to a controller, and then add a database operation method in the service.

release

Before publishing, you need to configure the database connection configuration in config/config.prod.js:

config.sequelize = {
  username: 'root'.password: ' '.database: 'template_node_egg'.host: '127.0.0.1'.dialect: 'mysql'
}
Copy the code

Activation:

yarn start
Copy the code

Stop:

yarn stop
Copy the code

Create scaffolding using Wy-CLI

Global installation:

npm i @wytxer/wy-cli -g
Copy the code

Then run wy init project-name to install scaffolding and select background scaffolding from the list:

❯ Background scaffolding (node.js + egg.js + Sequelize)Copy the code

Scaffolding common commands:

# installation
yarn install

# Start development
yarn dev

Start production environment
yarn start

# The production environment stops
yarn stop
Copy the code

Code and documentation

Thank you for reading, scaffolding will be long-term maintenance, welcome to download and use: background scaffolding GitHub address

Scaffolding usage documentation is also kept up to date.