Skip to content

Commit c154cb9

Browse files
committed
docs: quickstart/egg.md
1 parent a8ace9a commit c154cb9

File tree

3 files changed

+307
-6
lines changed

3 files changed

+307
-6
lines changed

docs/quickstart/README.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/quickstart/egg.md

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
---
2+
title: Your first Egg application
3+
---
4+
5+
It's time to get your hands dirty. In this guide, we'll walk you through every step of building a (really) simple Egg application.
6+
7+
:::tip Tips
8+
- This guide is for beginners who want to get started with an Egg application from scratch.
9+
- Most of the plugins are included in Egg by default. You can switch them on/off in the configurations.
10+
- More information can be found in [Guide](../guide/README.md).
11+
:::
12+
13+
## TodoMVC
14+
15+
We'll build a [TodoMVC](http://todomvc.com/) application from scratch, using Egg.
16+
17+
The complete version can be found at [eggjs/examples/todomvc](https://github.com/eggjs/examples/tree/master/todomvc).
18+
19+
<!-- ![](./images/todomvc.png) -->
20+
21+
## Creating an Egg aplication
22+
23+
### Preparation
24+
25+
- **OS**: All operating systems are supported, but `macOS` is recommended.
26+
- **Node.js**: If you are new to Node.js, there's an [installation guide here](./prepare.md).
27+
28+
### Scaffolding
29+
30+
There's a [tool](../workflow/development/init.md) for scaffolding Egg applications.
31+
32+
:::tip Tips
33+
The examples below use $ to represent the terminal prompt in a UNIX-like OS, it might be different in some occasions.
34+
:::
35+
36+
```bash
37+
$ mkdir demo && cd demo
38+
$ npm init egg --type=simple
39+
$ npm install
40+
```
41+
42+
### Directory
43+
44+
The `demo` directory will be looking like this. They are generated by following [the directory rules](../guide/directory.md) of an Egg application. We strongly recommend you to follow it when creating new folders.
45+
46+
```bash
47+
demo
48+
├── app
49+
│   ├── controller # Controllers
50+
│   │   └── home.js
51+
│   └── router.js # Routers
52+
├── config # Configurations
53+
│   ├── config.default.js
54+
│   └── plugin.js
55+
├── test # Testing files
56+
├── README.md
57+
└── package.json
58+
```
59+
60+
### `Controller`
61+
62+
[Controller](../guide/controller.md) is responsible for **parsing user requests**, **handling them** and **response back**.
63+
64+
```js
65+
// app/controller/home.js
66+
const { Controller } = require('egg');
67+
68+
class HomeController extends Controller {
69+
async index() {
70+
const { ctx } = this;
71+
ctx.body = 'hi, egg';
72+
}
73+
}
74+
75+
module.exports = HomeController;
76+
```
77+
78+
Every controller needs to mount to a certain `URL` which tells Egg when to handle incoming requests. In the case below, `/` would be handled with the controller you just wrote.
79+
80+
```js
81+
// app/router.js
82+
/**
83+
* @param {Egg.Application} app - egg application
84+
*/
85+
module.exports = app => {
86+
const { router, controller } = app;
87+
router.get('/', controller.home.index);
88+
};
89+
```
90+
91+
### Local Development
92+
93+
Egg comes with a [tool](../workflow/development/development.md) for local development.
94+
95+
- Getting your application up;
96+
- Watching file changes;
97+
- Generating `d.ts` files if you're using TypeScript;
98+
99+
To start your application:
100+
101+
```bash
102+
$ npm run dev
103+
```
104+
105+
Next, go to `http://127.0.0.1:7001` in your browser.
106+
107+
### Template Rendering
108+
109+
In most cases, we want to present web pages to users, using template rendering. But Egg doesn't come with this feature enabled by default. You have to choose a *template engine plugin* and enable it by yourself.
110+
111+
:::tip What is plugin?
112+
The plugin system is a special feature of Egg. It makes the core application simple, yet stable and highly efficient. You can use plugins for business logic reusing and building an eco-system.
113+
114+
Go to [Development - Plugins](../guide/plugin.md) to see more.
115+
:::
116+
117+
In this guide, we'll be using [Nunjucks](https://mozilla.github.io/nunjucks/) to render our pages.
118+
119+
To start, you need to install [egg-view-nunjucks] first.
120+
121+
```bash
122+
$ npm i egg-view-nunjucks --save
123+
```
124+
125+
Then, enable it.
126+
127+
```js
128+
// config/plugin.js
129+
exports.nunjucks = {
130+
enable: true,
131+
package: 'egg-view-nunjucks'
132+
};
133+
```
134+
135+
Every template file should be located in `app/view` and its enclosing folders.
136+
137+
```html
138+
<!-- app/view/home.tpl -->
139+
<html>
140+
...
141+
<script src="/public/main.js"></script>
142+
</html>
143+
```
144+
145+
Lastly, change your `Controller` into this.
146+
147+
```js
148+
class HomeController extends Controller {
149+
async index() {
150+
const { ctx } = this;
151+
// 渲染模板 `app/view/home.tpl`
152+
await ctx.render('home.tpl');
153+
}
154+
}
155+
```
156+
157+
### Static Files
158+
159+
Normally, static files are served through:
160+
161+
- Content Deliver Network (recommend);
162+
- Current application;
163+
164+
Egg comes with a handy plugin [egg-static] for serving static files in current application.
165+
166+
egg-static would mount the folder `app/public` to the route `/public` by default.
167+
168+
:::warning Warning
169+
- Files served by `egg-static` will be responsed with a `maxAge` header which indicates the browsers to cache for a year by default.
170+
- [CSRF mechanism](../ecosystem/security/csrf.md) is open by default. `AJAX` requests need to have a valid `token` so that they can be handled properly. If you are using axios, here's an example:
171+
172+
```js
173+
// app/public/main.js
174+
axios.defaults.headers.common['x-csrf-token'] = Cookies.get('csrfToken');
175+
```
176+
:::
177+
178+
### Configurations
179+
180+
It's quite common for developers to manage a bunch of [configurations](../guide/config.md). Egg's configuration feature would definately be helpful.
181+
182+
For example, to use [egg-view-nunjucks], you will have to add a few lines to `config/config.default.js`.
183+
184+
```js
185+
// config/config.default.js
186+
config.view = {
187+
defaultViewEngine: 'nunjucks',
188+
mapping: {
189+
'.tpl': 'nunjucks',
190+
'.html': 'nunjucks',
191+
},
192+
};
193+
```
194+
195+
:::warning Warning
196+
It's `./config`, not `./app/config`!
197+
:::
198+
199+
### `Service`
200+
201+
Normally, business logics are in the [Service](../guide/service.md). They can be called by the `Controller`.
202+
203+
Here is an example for creating a todo item.
204+
205+
```js
206+
// app/service/todo.js
207+
const { Service } = require('egg');
208+
209+
class TodoService extends Service {
210+
/**
211+
* create todo
212+
* @param {Todo} todo - todo info without `id`, but `title` required
213+
*/
214+
async create(todo) {
215+
// validate
216+
if (!todo.title) this.ctx.throw(422, 'task title required');
217+
218+
// normalize
219+
todo.id = Date.now().toString();
220+
todo.completed = false;
221+
222+
this.store.push(todo);
223+
return todo;
224+
}
225+
}
226+
```
227+
228+
Then, call it in `Controller`.
229+
230+
```js
231+
// app/controller/todo.js
232+
class TodoController extends Controller {
233+
async create() {
234+
const { ctx, service } = this;
235+
236+
// params validate, need `egg-validate` plugin
237+
// ctx.validate({ title: { type: 'string' } });
238+
239+
ctx.status = 201;
240+
ctx.body = await service.todo.create(ctx.request.body);
241+
}
242+
}
243+
```
244+
245+
### RESTful
246+
247+
Egg has [built-in support](../guide/router.md#RESTful-风格的-URL-定义) for RESTful routing.
248+
249+
```js
250+
// app/router.js
251+
module.exports = app => {
252+
const { router, controller } = app;
253+
254+
// RESTful mapping
255+
router.resources('/api/todo', controller.todo);
256+
};
257+
```
258+
259+
The controller `controller.todo` must implement these functions:
260+
261+
```js
262+
// app/controller/todo.js
263+
class TodoController extends Controller {
264+
// `GET /api/todo`
265+
async index() {}
266+
267+
// `POST /api/todo`
268+
async create() {}
269+
270+
// `PUT /api/todo`
271+
async update() {}
272+
273+
// `DELETE /api/todo`
274+
async destroy() {}
275+
}
276+
```
277+
278+
### Unit Testing
279+
280+
It is highly recommended to do the unit testing. Egg comes with [a tool](../workflow/development/unittest.md) for you to test your application.
281+
282+
```js
283+
// test/app/controller/todo.test.js
284+
const { app, mock, assert } = require('egg-mock/bootstrap');
285+
286+
describe('test/app/controller/todo.test.js', () => {
287+
it('should add todo', () => {
288+
return app.httpRequest()
289+
.post('/api/todo')
290+
.send({ title: 'Add one' })
291+
.expect('Content-Type', /json/)
292+
.expect('X-Response-Time', /\d+ms/)
293+
.expect(201)
294+
.expect(res => {
295+
assert(res.body.id);
296+
assert(res.body.title === 'Add one');
297+
assert(res.body.completed === false);
298+
});
299+
});
300+
});
301+
```
302+
303+
[Node.js]: http://nodejs.org
304+
[egg-static]: https://github.com/eggjs/egg-static
305+
[egg-view-nunjucks]: https://github.com/eggjs/egg-view-nunjucks
306+
[Nunjucks]: https://mozilla.github.io/nunjucks/

docs/zh/quickstart/egg.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class HomeController extends Controller {
163163
在本例中,我们使用 `Vue` 来写对应的前端逻辑,可以直接参见示例代码。
164164

165165
:::warning 注意事项
166-
- `static` 插件,线上会默认设置一年的 `magAge`
166+
- `static` 插件,线上会默认设置一年的 `maxAge`
167167
- 框架默认开启了 [CSRF 防护](../ecosystem/security/csrf.md),故 `AJAX` 请求需要带上对应的 `token`
168168

169169
```js

0 commit comments

Comments
 (0)