egg.js基础入门,前端迈向全栈开发的第一步

最近实习时接手了一个Egg.js + TypeScript的服务端的项目,mentor对我说可以让我先学习一下egg.js,于是最近都在捣鼓egg.js,有了一点小收获于是准备先记录下来,避免自己之后又忘记了。

1. Egg.js 简介

Egg.js是什么?它的官方文档是这样说的:

Egg.js 为企业级框架和应用而生。我们希望 Egg.js 能孕育出更多上层框架,帮助开发团队和开发人员降低开发和维护成本。

众所周知,node是具备后端开发的能力的,而egg.js就是为了方便后端开发而诞生的一种框架,就和我们之前介绍过的koa一样,而恰好,Egg又是继承于koa的,都是基于中间件开发,都是基于洋葱模型。

Egg 奉行"约定优于配置 "。按照一套统一的约定开发应用时,团队成员可以减少学习成本,不再是"钉子",能流动起来。未有约定的团队,沟通成本极高,因为每个人的开发习惯可能都不同,容易犯错。但约定并不意味着扩展性差,Egg 的扩展性极高,可根据不同团队的约定来定制框架。使用 Loader,框架能够根据不同环境定义默认配置,并覆盖 Egg 的默认约定。

这是官方文档对于它的描述。好的,废话不多说,我们来看看它的一些简单的语法吧。

2. Egg.js 目录结构介绍

我们可以使用这条命令npm init egg --type=simple来快速初始化一个egg.js项目,一般egg.js的目录结构会有这几项内容:

其中app目录与config目录是最重要的两个目录,我们着重介绍一下这两个:

我们说过,egg.js奉行的是"约定优于配置"的开发方式,所以每个文件夹是做什么的都是约定好的:

js 复制代码
app
├── controller        # 控制器(处理请求)
├── service           # 服务层(业务逻辑)
├── model             # 数据库模型(可选)
├── middleware        # 中间件
├── router.js         # 路由配置
config
├── config.default.js # 默认配置
├── plugin.js         # 插件配置

在egg.js中,还有一个非常重要的东西叫Context(上下文对象),各个文件夹之间的联通主要来靠它。每次请求会创建一个 Context 对象,它封装了Node.js 的 request 和 response 对象,并提供了一系列便捷方法。

我们可以在 Controller、Middleware、Service、Helper 中通过 this.ctx 访问。

接下来,我们将一一介绍一下app下的各个文件的作用是什么。

3. app/router.js 文件

作用:定义 URL 路由规则,将请求映射到 Controller。

示例配置:

js 复制代码
module.exports = app => {
  const { router, controller } = app;
  router.post('/user/create', controller.user.create);
  router.get('/user/list', controller.user.find);
};

当我们通过http请求访问/user/create/user/list,就会调用对应的UserController.create 方法。

4. app/controller 目录

作用:处理 HTTP 请求,负责路由与业务逻辑之间的桥梁。

示例文件:app/controller/user.js

js 复制代码
const Controller = require('egg').Controller;

class UserController extends Controller {
  async create() {
    const { ctx } = this;
    const { name, age } = ctx.request.body;
    // 调用 Service 处理业务逻辑
    const user = await ctx.service.user.createUser(name, age);
    ctx.body = { success: true, data: user };
  }

  async find() {
    const users = await this.ctx.service.user.getUsers();
    this.ctx.body = users;
  }
}
module.exports = UserController;

用途:定义 /user/create/user/find 路由对应的逻辑,联通service业务层。

5. app/service 目录

作用:封装业务逻辑(如数据库操作),供 Controller 调用。

示例文件:app/service/user.js

js 复制代码
const Service = require('egg').Service;

class UserService extends Service {
  async createUser(name, age) {
    // 假设使用 Egg.js 的 MySQL 插件
    const result = await this.app.mysql.insert('users', { name, age });
    return { id: result.insertId, name, age };
  }

  async getUsers() {
    return await this.app.mysql.select('users');
  }
}
module.exports = UserService;

用途:处理用户创建和查询的数据库操作。

6. app/middleware 目录

作用:存放中间件,用于拦截和处理请求。

示例文件:app/middleware/logger.js

js 复制代码
module.exports = (options, app) => {
  return async function logger(ctx, next) {
    const start = Date.now();
    await next(); // 执行后续中间件和路由
    const duration = Date.now() - start;
    console.log(`[${ctx.method}] ${ctx.url} - ${duration}ms`);
  };
};

配置启用:在 config/config.default.js 中:

js 复制代码
exports.middleware = ['logger']; // 启用中间件

7. app/view 目录

作用:存放模板文件(如 HTML 模板)。

示例文件:app/view/user/list.tpl

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <title>User List</title>
</head>
<body>
  <h1>Users</h1>
  <ul>
    {% for user in users %}
      <li>{{ user.name }} ({{ user.age }})</li>
    {% endfor %}
  </ul>
</body>
</html>

在 Controller 中渲染:

js 复制代码
async list() {
  const users = await this.ctx.service.user.getUsers();
  await this.ctx.render('user/list.tpl', { users });
}

8. app/extend 目录

作用:扩展 Egg.js 的核心对象(如 ApplicationContext 等)。

示例文件:app/extend/context.js

js 复制代码
module.exports = {
  formatUser(user) {
    return `User: ${user.name} (ID: ${user.id})`;
  }
};

使用扩展方法:

js 复制代码
// 在 Controller 中
ctx.formatUser(user); // 输出 "User: Alice (ID: 1)"

9. config 目录

作用:存放项目配置,区分不同环境(如开发、测试、生产)。

关键文件:

config.default.js(通用配置):

js 复制代码
exports.mysql = {
  client: {
    host: 'localhost',
    port: '3306',
    user: 'root',
    password: '123456',
    database: 'test',
  },
};

config.prod.js (生产环境覆盖配置)

js 复制代码
exports.mysql = {
  client: {
    host: 'prod.db.com', // 生产环境数据库地址
  },
};

10. 其他目录

  • app/public:存放静态文件(如图片、CSS)。
  • app/schedule:定时任务配置。
  • app/utils(非官方约定):存放工具类函数。

11. 总结

简单总结来说的话,就是用户访问 /user/listrouter.js 将请求路由到 UserController.list,Controller 调用 UserService.getUsers(),Service 通过 app.mysql 查询数据库,Controller 使用 ctx.render 渲染模板,返回 HTML 页面或 JSON 数据。

egg.js的内容远不止这些,本次只是对于egg.js的目录的一些简单的介绍,如果对你有帮助的话请点个赞吧。

相关推荐
隐藏用户_y10 分钟前
JavaScript闭包概念和应用详解
javascript·面试
我想说一句12 分钟前
CSS 基础知识小课堂:从“选择器”到“声明块”,带你玩转网页的时尚穿搭!
前端·javascript·面试
和雍23 分钟前
”做技术分享?苟都不做“做,做的就是 module.rules 加工过程
javascript·面试·webpack
仔仔 v1.031 分钟前
解决Vue3+uni-app导航栏高亮自动同步方案
前端·javascript·vue.js
Mintopia35 分钟前
Three.js 形变动画(Morph Target Animation):让 3D 模型跳起变形之舞
前端·javascript·three.js
烛阴1 小时前
模块/命名空间/全局类型如何共存?TS声明空间终极生存指南
前端·javascript·typescript
江城开朗的豌豆1 小时前
JavaScript篇:移动端点击的300ms魔咒:你以为用户手抖?其实是浏览器在搞事情!
前端·javascript·面试
华洛1 小时前
聊聊我们公司的AI应用工程师每天都干啥?
前端·javascript·vue.js
江城开朗的豌豆1 小时前
JavaScript篇:你以为事件循环都一样?浏览器和Node的差别让我栽了跟头!
前端·javascript·面试