阿里nodejs框架egg-js入门教程

一、前言

nodejs作为轻量级的web框架,在一些小项目上有着生态丰富, 开发快, 易运维的绝对优势。本篇博客是对阿里egg.js框架的学习记录, 最初写于2018年,更多特性请关注官网。

二、初始化

我们推荐直接使用脚手架,只需几条简单指令,即可快速生成项目:

1
2
3
4
$ npm i egg-init -g
$ egg-init egg-learn --type=simple
$ cd egg-learn
$ npm i

启动项目 npm run dev , 然后用webstorm导入项目

三、项目搭建

框架提供了 egg-mysql 插件来访问 MySQL 数据库。这个插件既可以访问普通的 MySQL 数据库,也可以访问基于 MySQL 协议的在线数据库服务。

安装与配置

安装对应的插件 egg-mysql :

1
npm i --save egg-mysql

开启插件:

1
2
3
4
5
// config/plugin.js
exports.mysql = {
enable: true,
package: 'egg-mysql',
};

单数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// config/config.${env}.js
config.mysql = {
// 单数据库信息配置
client: {
// host
host: 'localhost',
// 端口号
port: '3306',
// 用户名
user: 'root',
// 密码
password: 'root',
// 数据库名
database: 'test',
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};

创建数据库文件

初始化表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
Navicat Premium Data Transfer

Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50717
Source Host : localhost
Source Database : test

Target Server Type : MySQL
Target Server Version : 50717
File Encoding : utf-8

Date: 01/19/2018 10:44:32 AM
*/
DROP TABLE IF EXISTS `egg_user`;
CREATE TABLE `egg_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
`name` varchar(32) DEFAULT NULL COMMENT '用户名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

Service层

由于对 MySQL 数据库的访问操作属于 Web 层中的数据处理层,因此我们强烈建议将这部分代码放在 Service 层中维护。

下面是一个 Service 中访问 MySQL 数据库的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// app/service/index.js
const Service = require("egg").Service;

class IndexService extends Service{

//插入数据
async insert(){
const result = await this.app.mysql.insert("egg_user",{name:"admin"});
return {result};
}

//查询数据
async find(){
const result = await this.app.mysql.get("egg_user",{id:1});
return {result};
}
}

module.exports = IndexService;

Controller层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// app/controller/index.js
const Controller = require("egg").Controller;

class IndexController extends Controller{

async insert(){
console.log("插入数据");
const ctx = this.ctx;
const result = await ctx.service.index.insert();
ctx.body = result;
}

async find(){
console.log("查询数据");
const ctx = this.ctx;
const result = await ctx.service.index.find();
ctx.body = result;
}
}

module.exports = IndexController;

路由配置

1
2
3
4
5
6
7
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.get('/insert', controller.index.insert);
router.get('/find', controller.index.find);
};

启动项目即可测试

四、中间件

中间件支持以下几种方式:

在应用中使用中间件、
在框架和插件中使用中间件、
在路由中使用中间件

我们只介绍在路由中使用中间件,只需对路由文件改造即可:

1
2
3
4
5
6
7
8
9
module.exports = app => {
const { router, controller } = app;

const logger = app.middleware.logger();

router.get('/', logger, controller.home.index);
router.get('/insert', logger, controller.index.insert);
router.get('/find', logger, controller.index.find);
};

中间件文件如下:

1
2
3
4
5
6
7
8
//app/middleware/logger.js
module.exports = options => {
return async function logger(ctx,next) {
console.log("中间件in");
await next();
console.log("中间件out");
};
};

五、模板

框架内置 egg-view 作为模板解决方案,并支持多模板渲染,每个模板引擎都以插件的方式引入,但保持渲染的 API 一致。

以下以官方支持的 View 插件 egg-view-nunjucks 为例

引入view插件

1
npm i egg-view-nunjucks --save

启用插件

1
2
3
4
5
// config/plugin.js
exports.nunjucks = {
enable: true,
package: 'egg-view-nunjucks',
};

配置插件

1
2
3
4
5
6
config.view = {
defaultViewEngine: 'nunjucks',
mapping: {
'.html': 'nunjucks',
},
};

创建模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//app/view/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<h2>欢迎您 {{result.name}}</h2>a
</div>

</body>
</html>

Controller

1
2
3
4
5
6
async indexView(){
console.log("渲染模板");
const ctx = this.ctx;
const result = await ctx.service.index.find();
await ctx.render("index.html",result);
}

路由

1
router.get('/view', logger,  controller.index.indexView);