一、入门
1. 初始化项目
| mkdir egg-example
 cd egg-example
 npm init egg --type=simple
 npm i
 yarn dev
 
 | 
2. 安装并配置模板引擎插件
(1) 安装:npm i egg-view-nunjucks --save
(2) 开启插件:
| exports.nunjucks = {
 enable: true,
 package: "egg-view-nunjucks"
 };
 
 | 
| config.view = {
 defaultViewEngine: "nunjucks",
 mapping: {
 ".tpl": "nunjucks"
 }
 };
 
 | 
二、开始使用
1. 创建模板文件
| <html>
 <head>
 <title>Hacker News</title>
 <link rel="stylesheet" href="/public/css/news.css" />
 </head>
 <body>
 <ul class="news-view view">
 {% for item in list %}
 <li class="item">
 <a href="{{ item.url }}">{{ item.title }}</a>
 </li>
 {% endfor %}
 </ul>
 </body>
 </html>
 
 | 
2. 创建静态资源文件 news.css 到 public/css
| ul {list-style: none;
 margin: 0;
 padding: 0;
 }
 
 .item {
 margin: 10px 0;
 }
 
 .link {
 color: orange;
 text-decoration: none;
 transform: translateY(10px);
 }
 
 .link:hover {
 color: rgb(136, 131, 131);
 }
 
 .time {
 color: rgb(136, 131, 131);
 margin-left: 20px;
 }
 
 | 
3. 添加 Controller 和 Router
(1)、新建 news.js 到 //app/controller
| const Controller = require("egg").Controller;
 
 class NewsController extends Controller {
 async list() {
 const dataList = {
 list: [
 {
 id: 1,
 title: "this is news 1",
 url: "/news/1"
 },
 {
 id: 2,
 title: "this is news 2",
 url: "/news/2"
 }
 ]
 };
 await this.ctx.render("news/list.tpl", dataList);
 }
 }
 
 module.exports = NewsController;
 
 | 
(2)、router.js 添加语句:router.get('/news', controller.news.list);
(3)、查看效果:yarn dev => 打开 http://127.0.0.1:7002/news
4. 编写业务逻辑,爬取 hacker-news 数据
(1) 新建目录:// app/service/news.js,这里请求时设置了 proxy,是因为 hacker-news 的 api 被墙了
| "use strict";const Service = require("egg").Service;
 
 class NewsService extends Service {
 async list(page = 1) {
 
 const { serverUrl, pageSize } = this.config.news;
 
 const { data: idList } = await this.ctx.curl(
 `${serverUrl}/topstories.json`,
 {
 enableProxy: true,
 proxy: "http://127.0.0.1:1080",
 data: {
 orderBy: '"$key"',
 startAt: `"${pageSize * (page - 1)}"`,
 endAt: `"${pageSize * page - 1}"`
 },
 dataType: "json"
 }
 );
 
 
 const newsList = await Promise.all(
 Object.keys(idList).map(key => {
 const url = `${serverUrl}/item/${idList[key]}.json`;
 
 return this.ctx.curl(url, {
 enableProxy: true,
 proxy: "http://127.0.0.1:1080",
 dataType: "json"
 });
 })
 );
 return newsList.map(res => res.data);
 }
 }
 
 module.exports = NewsService;
 
 | 
(2) // app/controller/news.js 修改语句
| async list() {const ctx = this.ctx;
 const page = ctx.query.page || 1;
 const newsList = await ctx.service.news.list(page);
 await ctx.render('news/list.tpl', { list: newsList });
 }
 
 | 
(3) // config/config.default.js 添加下面代码
| config.news = {pageSize: 5,
 serverUrl: "https://hacker-news.firebaseio.com/v0"
 };
 
 | 
5. 编写扩展插件 moment,美化时间
| "use strict";
 const moment = require("moment");
 
 exports.relativeTime = time => moment(new Date(time * 1000)).fromNow();
 
 | 
| // views/news/list.tpl<html>
 <head>
 <title>Hacker News</title>
 <link rel="stylesheet" href="/public/css/news.css" />
 </head>
 <body>
 <ul class="news-view view">
 {% for item in list %}
 <li class="item">
 <a class="link" href="{{ item.url }}">{{ item.title }}</a>
 <span class="time">{{ helper.relativeTime(item.time) }}</span>
 </li>
 {% endfor %}
 </ul>
 </body>
 </html>
 
 | 
6. 站点禁止百度爬虫访问
(1) app/middleware/robot.js
| "use strict";
 module.exports = (options, app) => {
 return async function robotMiddleware(ctx, next) {
 const source = ctx.get("user-agent") || "";
 const match = options.ua.some(ua => ua.test(source));
 if (match) {
 ctx.status = 403;
 ctx.message = "Go away, robot.";
 } else {
 await next();
 }
 };
 };
 
 | 
(2) config/config.default.js 添加如下代码
| config.middleware = ["robot"];
 
 config.robot = {
 ua: [/Baiduspider/i]
 };
 
 | 
7. 单元测试
(1) // test/app/middleware/robot.test.js
| "use strict";const { app, mock, assert } = require("egg-mock/bootstrap");
 
 describe("test/app/middleware/robot.test.js", () => {
 it("should block robot", () => {
 return app
 .httpRequest()
 .get("/")
 .set("User-Agent", "Baiduspider")
 .expect(403);
 });
 });
 
 | 
(2) 执行测试脚本 yarn test-local
本文标题:Egg 快速上手
文章作者:Canace
发布时间:2020-11-27
最后更新:2025-09-14
原始链接:https://canace.site/egg/
版权声明:转载请注明出处