Step-by-Step: A Preliminary Understanding of Enterprise-Level Application Code Structure and Database Configuration

12002

1. JianghuJS Directory Structure

In JianghuJS, the directory structure follows the eggjs structural specification, as shown below:

├── app  
│   ├── common  
│   ├── constant  
│   │   ├── constant.js  
│   │   └── error.js  
│   ├── controller  
│   ├── public  
│   ├── schedule  
│   ├── service  
│   └── view  
├── config  
│   ├── config.default.js  
│   ├── config.local.js  
│   ├── config.prod.js  
│   ├── config.unittest.js  
│   └── plugin.js  
├── app.js  
├── jsconfig.json  
├── package.json  
├── sql  
│   └── init.sql  
└── upload  

2. Description of Each Directory

  • app: The main code directory of the application
    • common: Stores commonly used tools, static methods, etc.
    • constant: Stores constant definitions
      • constant.js: Constant definition file
      • error.js: Error message definition file
    • controller: Stores controllers for exposed interfaces
    • public: Static resources directory
    • schedule: Stores scheduled tasks
    • service: Stores the service directory for application protocols
    • view: Stores the directory for pages
  • config: Stores configuration files
    • config.default.js: Default configuration file
    • config.local.js: Configuration file used during npm run dev
    • config.prod.js: Configuration file used during npm run start
    • config.unittest.js: Configuration file used during npm run test
    • plugin.js: Plugin configuration file
  • app.js: The entry file for custom initialization work at startup
  • jsconfig.json: File used to configure syntax checking, intelligent sensing, and other related settings for JavaScript projects
  • package.json: Project dependencies and configuration file
  • sql: Stores SQL files
  • init.sql: Initialization SQL file
  • upload: Directory for uploaded files

3. [JianghuJS Core] Middleware - Chained Calls

Middleware is essentially a function that can intercept, process requests, and pass them to the next middleware or routing handler. The use of middleware allows us to break down the request handling process, modularize the processing logic, and facilitate code reuse and maintenance.

In Egg.js, middleware is passed through the app and ctx objects. For each request, Egg.js passes the ctx object to each middleware function in the order of the middleware and executes their logic. During the execution of the middleware, the middleware function can modify the ctx object as needed and decide whether to pass the request to the next middleware or routing handler. This creates a chained request handling process, ultimately yielding the desired result.

In addition to the core idea of chained calls, Egg.js middleware also has the following characteristics:

  • Multiple middleware can be defined to form an array of middleware.
  • Middleware can be registered through the app object.
  • The execution order of middleware can be controlled by defining the order of middleware.
  • Middleware can share state through the ctx object, facilitating data transmission and processing.
  • Middleware can intercept, modify, and terminate requests as needed.

Let's start by writing a simple gzip middleware to see how middleware is written.

// app/middleware/gzip.js  
const isJSON = require('koa-is-json');  
const zlib = require('zlib');  

async function gzip(ctx, next) {  
  await next();  

  // Convert the response body to gzip after subsequent middleware execution is complete  
  let body = ctx.body;  
  if (!body) return;  
  if (isJSON(body)) body = JSON.stringify(body);  

  // Set gzip body and correct response header  
  const stream = zlib.createGzip();  
  stream.end(body);  
  ctx.body = stream;  
  ctx.set('Content-Encoding', 'gzip');  
}