本文详细介绍了Egg.js学习的各个方面,包括框架的基本概念、快速上手指南和应用开发的最佳实践。文章还涵盖了Egg.js的基础配置、插件和中间件的使用方法,以及数据库操作和API接口构建等内容。此外,文中提供了错误处理和性能优化的进阶技巧,帮助开发者更好地理解和使用Egg.js。Egg.js学习过程中,你还将找到丰富的资源和社区支持,以进一步提升你的开发技能。
Egg.js 是一个企业级 Node.js Web 应用框架,基于 Koa 框架构建,并提供了丰富的内置插件和中间件支持。它旨在帮助企业开发者高效地构建稳定、可靠、可扩展的应用程序。
Egg.js 采用了模块化的架构设计,使得应用易于扩展和维护。每个功能模块可以独立开发、测试和部署,降低了代码复杂度。
Egg.js 内置了多种中间件,如路由处理、静态文件服务、错误处理等,极大地方便了开发者进行快速开发。
Egg.js 提供了丰富的配置选项,可以方便地调整应用的行为。开发者可以根据自己的需求对各个配置项进行设置,灵活地控制应用的各个方面。
Egg.js 为企业级应用开发提供了许多高级特性,如多进程、负载均衡、日志记录等,使得应用更加健壮和高效。
Egg.js 主要适用于以下场景:
在使用 Egg.js 之前,需要确保已经安装了 Node.js 和 npm。以下是安装步骤:
访问 Node.js 官方网站(https://nodejs.org/)下载最新版本的 Node.js,安装完成后会自动安装 npm。
node -v npm -v
以上命令会输出 Node.js 和 npm 的版本号,表示安装成功。
安装 Egg.js 需要使用 npm 来完成。在终端中运行以下命令:
npm install -g egg-init
这条命令会将 egg-init
命令安装到全局环境中,方便后续使用。
完成 Egg.js 的安装后,可以通过 egg-init
命令来创建一个新的 Egg.js 项目。以下是创建项目的步骤:
egg-init --type=official myapp
这会创建一个名为 myapp
的目录,并在该目录下生成一个基本的 Egg.js 应用结构。
cd myapp
npm i npm start
执行以上命令后,Egg.js 应用将会启动,并在浏览器中打开 http://localhost:7001/ ,可以看见默认的欢迎页面。
Egg.js 的应用由一个主文件 app.js
和一系列模块组成,每个模块都有自己的目录结构。默认情况下,Egg.js 的应用目录结构如下:
myapp ├── app │ ├── controller │ ├── middleware │ ├── router │ ├── service │ └── config ├── config │ └── config.default.js ├── package.json └── README.md
app
: 应用的核心目录。
controller
: 存放控制器文件,负责处理路由请求。middleware
: 存放中间件文件,用于处理请求前后的逻辑。router
: 存放路由配置文件,定义应用的路由。service
: 存放服务文件,用于处理业务逻辑。config
: 存放配置文件。
config.default.js
: 默认配置文件。package.json
: 项目配置文件。README.md
: 项目说明文件。app.js
: 应用入口文件,定义了 Egg.js 应用的基本配置和初始化操作。Egg.js 的插件系统允许开发者扩展应用的功能。插件可以是独立的 Node.js 模块,也可以是 Egg.js 的内置插件。
npm install --save egg-logger
module.exports = () => { return { plugins: { logger: { enable: true, package: 'egg-logger', }, }, }; };
中间件是处理请求和响应的模块,可以在请求处理链中添加额外的功能。Egg.js 内置了一些中间件,也可以自定义中间件。
// app/middleware/myMiddleware.js module.exports = (options) => { return async (ctx, next) => { ctx.response.set('X-Powered-By', 'Egg.js'); await next(); }; };
module.exports = () => { return { middleware: { myMiddleware: { enable: true, path: 'myMiddleware', }, }, }; };
Egg.js 的配置文件位于 config
目录下,主要包含 config.default.js
和 config.${env}.js
(如 config.local.js
)。
config.default.js
文件定义了应用的基础配置项。例如:
module.exports = () => { return { baseDir: '.', // 应用根目录 appDir: 'app', // 应用目录 configDir: 'config', // 配置目录 enableSecret: true, // 是否启用应用密钥 secret: 'eggjs', // 应用密钥 proxy: false, // 是否启用代理 ipWhitelist: [], // 白名单IP地址 }; };
config.${env}.js
文件用于定义特定环境下的配置项。例如:
module.exports = () => { return { ...require('../config.default'), // 继承默认配置 logger: { consoleLevel: 'INFO', // 控制台日志级别 }, port: 7001, // 端口号 }; };
在 Egg.js 中,可以通过 ORM(对象关系映射)来操作数据库。这里使用 Sequelize 作为 ORM 框架。
npm install --save sequelize npm install --save pg pg-hstore
// config/config.default.js module.exports = () => { return { ... sequelize: { dialect: 'postgres', host: 'localhost', port: 5432, database: 'mydb', username: 'postgres', password: 'password', }, }; };
// app/model/user.js module.exports = app => { const { Sequelize, Model } = app; const User = app.model.define('User', { id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, }, username: Sequelize.STRING, password: Sequelize.STRING, }); return User; };
为了确保数据库连接正常,可以在 app.js
中添加以下测试代码:
// app.js module.exports = app => { app.on('ready', () => { app.model.sequelize .authenticate() .then(() => { console.log('数据库连接成功'); }) .catch(err => { console.error('数据库连接失败', err); }); }); };
// app/controller/user.js module.exports = app => { class UserController extends app.Controller { async list() { const users = await app.model.User.findAll(); this.success(users); } async create() { const { ctx } = this; const user = await ctx.model.User.create(ctx.request.body); this.success(user); } } return UserController; };
// app/router.js module.exports = app => { const { router, controller } = app; router.get('/users', controller.user.list); router.post('/users', controller.user.create); };
// app/middleware/response.js module.exports = () => { return async (ctx, next) => { await next(); if (ctx.response.status === 204) { ctx.response.body = ''; } }; };
// config/config.default.js module.exports = () => { return { ... middleware: { response: { enable: true, path: 'response', }, }, }; };
为了确保 API 接口正常工作,可以使用 Postman 或者 curl 进行测试。例如:
curl -X POST http://localhost:7001/users -H "Content-Type: application/json" -d '{"username": "test", "password": "test"}'
npm install --save egg-jwt
// config/config.default.js module.exports = () => { return { ... jwt: { secret: 'secret', // 密钥 }, }; };
// app/middleware/auth.js module.exports = () => { return async (ctx, next) => { const { app } = ctx; const { jwt } = app; const { authorization } = ctx.request.header; const token = authorization && authorization.split(' ')[1]; if (token) { try { const decoded = await jwt.verify(token, app.config.jwt.secret); ctx.jwt = decoded; await next(); } catch (err) { ctx.status = 401; ctx.body = 'Unauthorized'; } } else { ctx.status = 401; ctx.body = 'Unauthorized'; } }; };
// app/router.js module.exports = app => { const { router, controller } = app; router.get('/users', controller.user.list); router.post('/users', controller.user.create); router.get('/protected', [app.middleware.auth()], controller.user.list); };
npm install --save egg-permission
// config/config.default.js module.exports = () => { return { ... permission: { enable: true, module: 'user', actions: [ { name: 'list', allow: ['admin'] }, { name: 'create', allow: ['admin', 'user'] }, ], }, }; };
// app/middleware/permission.js module.exports = () => { return async (ctx, next) => { const { app, jwt } = ctx; const { permission } = app; const { action } = ctx.params; if (permission[action]) { if (permission[action].allow.includes(jwt.role)) { await next(); } else { ctx.status = 403; ctx.body = 'Forbidden'; } } else { await next(); } }; };
// app/router.js module.exports = app => { const { router, controller } = app; router.get('/users', controller.user.list); router.post('/users', controller.user.create); router.get('/protected', [app.middleware.auth(), app.middleware.permission()], controller.user.list); };
为了确保用户认证和权限管理功能正常工作,可以编写单元测试。例如:
// tests/controller/user.test.js const request = require('supertest'); const app = require('../app'); describe('UserController', () => { it('should list users', async () => { const res = await request(app).get('/users'); expect(res.status).toBe(200); expect(res.body).toBeDefined(); }); it('should create a user', async () => { const res = await request(app).post('/users').send({ username: 'test', password: 'test' }); expect(res.status).toBe(201); expect(res.body).toBeDefined(); }); it('should return unauthorized for protected route', async () => { const res = await request(app).get('/protected'); expect(res.status).toBe(401); }); });
在 Egg.js 中,错误处理通常由中间件来实现。可以通过自定义中间件来捕获和处理错误。
// app/middleware/error.js module.exports = () => { return async (ctx, next) => { try { await next(); } catch (err) { ctx.status = err.status || 500; ctx.body = err.message; } }; };
// config/config.default.js module.exports = () => { return { ... middleware: { error: { enable: true, path: 'error', }, }, }; };
为了确保错误处理中间件正常工作,可以编写单元测试。例如:
// tests/middleware/error.test.js const request = require('supertest'); const app = require('../app'); describe('Error Middleware', () => { it('should handle errors', async () => { const res = await request(app).get('/error'); expect(res.status).toBe(500); expect(res.text).toBe('Internal Server Error'); }); });
使用 HTTP/2 协议:HTTP/2 协议可以减少请求延迟,提高应用性能。
使用缓存:合理利用缓存可以减少数据库查询次数,提高应用性能。
使用 Docker:使用 Docker 可以方便地进行应用部署和版本管理。
使用 Nginx 反向代理:Nginx 可以作为反向代理服务器,实现负载均衡和静态文件服务。
Egg.js 提供了一些内置工具,可以帮助开发者进行开发和调试。
egg-bin
是一个命令行工具,可以直接运行 Egg.js 应用,而不需要安装全局 Egg.js。
node_modules/.bin/egg-bin dev
egg-logger
是 Egg.js 的内置日志插件,用于记录应用日志。
egg-mock
是 Egg.js 的内置插件,用于模拟 HTTP 请求,方便进行单元测试。
npm install --save egg-mock
// config/config.default.js module.exports = () => { return { plugins: { mock: { enable: true, package: 'egg-mock', }, }, }; };
egg-security
是 Egg.js 的内置插件,提供了安全相关的中间件,如 CSRF、XSS 等。
npm install --save egg-security
// config/config.default.js module.exports = () => { return { plugins: { security: { enable: true, package: 'egg-security', }, }, }; };
错误:Cannot find module 'egg'
egg-init
,可以使用以下命令进行全局安装:
npm install -g egg-init
Cannot find module './config/config.default.js'
config/config.default.js
。更多资源和教程可以在 Egg.js 官方网站和社区中找到。